The CSS Podcast – 020: Hàm
Cho đến nay, trong khoá học này, bạn đã được làm quen với một số hàm CSS.
Trong mô-đun lưới, bạn đã được giới thiệu về minmax()
và fit-content()
, giúp bạn định kích thước các phần tử.
Trong mô-đun color (màu), bạn đã được giới thiệu về rgb()
và hsl()
để giúp xác định màu sắc.
Giống như nhiều ngôn ngữ lập trình khác, CSS có rất nhiều hàm tích hợp sẵn mà bạn có thể truy cập bất cứ khi nào cần.
Mỗi hàm CSS đều có một mục đích cụ thể. Trong bài học này, bạn sẽ có được thông tin tổng quan cấp cao, giúp bạn hiểu rõ hơn về vị trí và cách sử dụng các hàm đó.
Hàm là gì?
Hàm là một đoạn mã có tên, độc lập, hoàn thành một tác vụ cụ thể. Hàm được đặt tên để bạn có thể gọi hàm đó trong mã và truyền dữ liệu vào hàm. Đây được gọi là truyền đối số.
Nhiều hàm CSS là hàm thuần tuý, nghĩa là nếu bạn truyền cùng một đối số vào các hàm này, thì các hàm này sẽ luôn trả về cùng một kết quả, bất kể điều gì đang xảy ra trong phần còn lại của mã.
Các hàm này thường sẽ tính toán lại khi giá trị thay đổi trong CSS, tương tự như các phần tử khác trong ngôn ngữ, chẳng hạn như các giá trị được tính toán theo kiểu thác nước như currentColor
.
Trong CSS, bạn chỉ có thể sử dụng các hàm được cung cấp thay vì tự viết hàm, nhưng các hàm có thể được lồng trong nhau trong một số ngữ cảnh, giúp các hàm linh hoạt hơn. Chúng ta sẽ trình bày chi tiết hơn về vấn đề này ở phần sau của mô-đun này.
Bộ chọn chức năng
.post :is(h1, h2, h3) {
line-height: 1.2;
}
Bạn đã tìm hiểu về bộ chọn chức năng trong mô-đun lớp giả, mô-đun này trình bày chi tiết các hàm như :is()
và :not()
.
Các đối số được truyền vào các hàm này là bộ chọn CSS, sau đó được đánh giá.
Nếu có phần tử khớp, phần còn lại của quy tắc CSS sẽ được áp dụng cho các phần tử đó.
Thuộc tính tuỳ chỉnh và var()
:root {
--base-color: #ff00ff;
}
.my-element {
background: var(--base-color);
}
Thuộc tính tuỳ chỉnh là một biến cho phép bạn tạo mã thông báo cho các giá trị trong mã CSS.
Các thuộc tính tuỳ chỉnh cũng chịu ảnh hưởng của hiệu ứng thác nước, nghĩa là các thuộc tính này có thể được thao tác theo ngữ cảnh hoặc được xác định lại.
Thuộc tính tuỳ chỉnh phải có tiền tố là hai dấu gạch ngang (--
) và phân biệt chữ hoa chữ thường.
Hàm var()
lấy một đối số bắt buộc: thuộc tính tuỳ chỉnh mà bạn đang cố gắng trả về dưới dạng giá trị.
Trong đoạn mã trước, hàm var()
đã truyền --base-color
dưới dạng đối số. Nếu --base-color
được xác định, thì var()
sẽ trả về giá trị.
.my-element {
background: var(--base-color, hotpink);
}
Bạn cũng có thể truyền giá trị khai báo dự phòng vào hàm var()
.
Điều này có nghĩa là nếu không tìm thấy --base-color
, thì thông báo khai báo đã truyền sẽ được sử dụng, trong trường hợp của mẫu này là màu hotpink
.
Hàm trả về một giá trị
Hàm var()
chỉ là một trong những hàm CSS trả về một giá trị.
Các hàm như attr()
và url()
tuân theo cấu trúc tương tự như var()
– bạn truyền một hoặc nhiều đối số và sử dụng các đối số đó ở bên phải của phần khai báo CSS.
a::after {
content: attr(href);
}
Hàm attr()
ở đây đang lấy nội dung của thuộc tính href
của phần tử <a>
và đặt nội dung đó làm content
của phần tử giả ::after
.
Nếu giá trị của thuộc tính href
của phần tử <a>
thay đổi, thì giá trị này sẽ tự động được phản ánh trong thuộc tính content
này.
.my-element {
background-image: url('/path/to/image.jpg');
}
Hàm url()
nhận một URL chuỗi và được dùng để tải hình ảnh, phông chữ và nội dung.
Nếu bạn không truyền một URL hợp lệ hoặc không tìm thấy tài nguyên mà URL trỏ đến, thì hàm url()
sẽ không trả về giá trị nào.
Hàm màu
Bạn đã tìm hiểu tất cả về các hàm màu trong mô-đun color. Nếu chưa đọc bài viết đó, bạn nên đọc.
Một số hàm màu có sẵn trong CSS là rgb()
, hsl()
, lab()
, lch()
, oklab()
, oklch()
và color()
.
Tất cả các hàm này đều có dạng tương tự nhau, trong đó các đối số cấu hình được truyền vào và một màu được trả về.
Biểu thức toán học
Giống như nhiều ngôn ngữ lập trình khác, CSS cung cấp các hàm toán học hữu ích để hỗ trợ nhiều loại phép tính.
Hàm số học
calc()
Hàm calc()
nhận một biểu thức toán học duy nhất làm tham số.
Biểu thức toán học này có thể là sự kết hợp của các loại, chẳng hạn như độ dài, số, góc và tần suất. Bạn cũng có thể kết hợp các đơn vị.
.my-element {
width: calc(100% - 2rem);
}
Trong ví dụ này, hàm calc()
đang được dùng để định kích thước chiều rộng của một phần tử là 100% của phần tử mẹ chứa phần tử đó, sau đó xoá 2rem
khỏi giá trị đã tính toán đó.
:root {
--root-height: 5rem;
}
.my-element {
width: calc(calc(10% + 2rem) * 2);
height: calc(var(--root-height) * 3);
}
Bạn có thể lồng hàm calc()
vào một hàm calc()
khác.
Bạn cũng có thể truyền các thuộc tính tuỳ chỉnh trong hàm var()
dưới dạng một phần của biểu thức.
min()
và max()
Hàm min()
trả về giá trị được tính nhỏ nhất của một hoặc nhiều đối số đã truyền.
Hàm max()
làm ngược lại: lấy giá trị lớn nhất của một hoặc nhiều đối số đã truyền.
.my-element {
width: min(20vw, 30rem);
height: max(20vh, 20rem);
}
Trong ví dụ này, chiều rộng phải là giá trị nhỏ nhất giữa 20vw
(20% chiều rộng khung nhìn) và 30rem
.
Chiều cao phải là giá trị lớn nhất giữa 20vh
(20% chiều cao khung nhìn) và 20rem
.
clamp()
Hàm clamp()
nhận 3 đối số: kích thước tối thiểu, kích thước lý tưởng và kích thước tối đa.
h1 {
font-size: clamp(2rem, 1rem + 3vw, 3rem);
}
Trong ví dụ này, font-size
sẽ linh hoạt dựa trên chiều rộng của khung nhìn.
Đơn vị vw
được thêm vào đơn vị rem
để hỗ trợ thu phóng màn hình, vì bất kể mức thu phóng nào, đơn vị vw
cũng sẽ có cùng kích thước.
Việc nhân với đơn vị rem
(dựa trên kích thước phông chữ gốc) sẽ cung cấp cho hàm clamp()
một điểm tính toán tương đối.
Bạn có thể tìm hiểu thêm về các hàm min()
, max()
và clamp
() trong
bài viết này về các hàm này.
Hàm lượng giác
Hàm lượng giác cho phép bạn tìm thấy bất kỳ điểm nào trên một vòng tròn dựa trên góc, mô hình các hiện tượng chu kỳ như sóng âm, mô tả quỹ đạo và nhiều hiện tượng khác. Trong CSS, bạn có thể sử dụng các hàm lượng giác để đặt thuộc tính dựa trên độ xoay, ảnh động theo thời gian, xoay các phần tử dựa trên một điểm và các mục đích sử dụng khác.
Để biết thêm thông tin và ví dụ, hãy xem bài viết về hàm lượng giác.
sin()
, cos()
và tan()
Các hàm sin()
, cos()
và tan()
nhận một đối số góc và trả về sin, cos và tang tương ứng. Hàm sin()
và cos()
trả về một số nằm trong khoảng từ -1
đến 1
. Hàm tan()
trả về một số nằm trong khoảng từ -Infinity
đến +Infinity
. Đối số góc có thể là bất kỳ đơn vị góc nào được hỗ trợ.
:root {
--sine-degrees: sin(45deg); /* returns 0.7071 */
--sine-radians: sin(0.7853rad); /* returns 0.7071 */
}
Trong ví dụ trước, --sine-degrees
và --sine-radians
có cùng một giá trị (trong trường hợp này là 0.7071
).
Trong ví dụ trước, các hàm sin()
và cos()
được dùng để tạo ảnh động dao động trên trục x
và y
bằng cách nhân kết quả với bán kính đã chỉ định. Việc sử dụng cả hai hàm cùng một lúc cho phép tạo ảnh động xoay quanh.
Chúng ta sử dụng một thuộc tính tuỳ chỉnh, --angle
, để tạo ảnh động góc một cách mượt mà cho tất cả các lệnh gọi hàm.
asin()
, acos()
và atan()
asin()
, acos()
và atan()
là hàm nghịch đảo của các hàm sin()
, cos()
và tan()
, lấy một số làm đối số và trả về một giá trị góc từ -90deg
đến 90deg
. Hàm asin()
và acos()
chấp nhận số từ -1
đến 1
, trong khi hàm atan()
chấp nhận số từ -Infinity
đến +Infinity
.
:root {
--degrees: asin(0.7071); /* returns 45deg */
}
atan2()
Hàm atan2()
nhận hai đối số đại diện cho một điểm tương ứng với gốc và trả về góc đại diện cho hướng đến điểm đó. Bạn có thể sử dụng phương thức này để xoay các phần tử hướng về một điểm cụ thể. Các đối số có thể là số, đơn vị kích thước hoặc tỷ lệ phần trăm, nhưng cả hai đối số đều phải thuộc cùng một loại.
Trong ví dụ trên, hàm atan2()
được dùng để xác định góc giữa tâm của khung nhìn và vị trí chuột hiện tại. Lưu ý rằng giá trị y
là đối số đầu tiên và giá trị x
là đối số thứ hai. Sau đó, góc này được dùng để định vị "đồng tử" tương ứng với tâm của "mắt", để chúng theo dõi con chuột.
hypot()
Hàm hypot()
nhận hai đối số chiều dài đại diện cho các cạnh của một tam giác vuông và trả về chiều dài của cạnh huyền. Bạn có thể sử dụng hàm này làm lối tắt để tính toán bằng hàm số mũ. Cả hai đối số phải thuộc cùng một loại đơn vị và hypot()
sẽ trả về cùng một loại.
:root {
--use-ems: hypot(3em, 4em); /* returns 5em */
--use-px: hypot(30px, 40px); /* returns 50px */
}
Hàm số mũ
pow()
và exp()
Hàm pow()
nhận hai đối số số, cơ số và số mũ, đồng thời nâng cơ số lên lũy thừa của số mũ. Cả hai đối số phải là số không có đơn vị. Hàm exp()
nhận một đối số duy nhất và tương đương với việc gọi hàm pow()
có cơ sở là e.
.my-element {
width: calc(10px * pow(4, 2); /* 10px * (4 * 4) == 160px */
}
sqrt()
Hàm sqrt()
nhận một đối số dạng số và trả về căn bậc hai của đối số đó. Đối số không được chứa đơn vị.
:root {
--root: sqrt(25); /* returns 5 */
}
log()
Hàm log()
trả về logarit của một giá trị số. Nếu truyền một đối số, hàm này sẽ trả về hàm logarit tự nhiên. Nếu bạn truyền đối số thứ hai, hàm log()
sẽ sử dụng đối số thứ hai làm cơ sở cho logarit.
:root {
--log2: log(16, 2); /* returns 4 */
--logn: log(16); /* returns 2.7725 */
}
Các hàm liên quan đến chữ ký
abs()
Hàm abs()
nhận một đối số dạng số và trả về giá trị tuyệt đối (dương) của giá trị đối số.
.my-element {
color: rgba(0, 0, 0, abs(-1));
}
Trong ví dụ trước, giá trị alpha
của -1
sẽ dẫn đến văn bản trong suốt, nhưng hàm abs()
trả về giá trị tuyệt đối của 1
, dẫn đến văn bản hoàn toàn mờ.
sign()
Hàm sign()
nhận một đối số dạng số và trả về dấu của đối số.
Giá trị dương trả về 1
và giá trị âm trả về -1
. Giá trị 0 sẽ trả về 0
.
.my-element {
top: calc(50vh + 25vh * sign(var(--value));
}
Trong các ví dụ trước, nếu --value
dương, thì giá trị trên cùng sẽ là 75vh
. Nếu giá trị này là âm, thì giá trị cao nhất sẽ là 25vh
. Nếu giá trị này bằng 0, thì giá trị hàng đầu sẽ là 50vh
.
Hình dạng
Các thuộc tính CSS clip-path
, offset-path
và shape-outside
sử dụng các hình dạng để cắt hộp của bạn một cách trực quan hoặc cung cấp hình dạng để nội dung lưu chuyển xung quanh.
Có các hàm hình dạng có thể được sử dụng với cả hai thuộc tính này.
Các hình dạng đơn giản như
circle()
,
ellipse()
và
inset()
sẽ lấy các đối số cấu hình để định kích thước cho các hình dạng đó.
Các hình dạng phức tạp hơn, chẳng hạn như
polygon()
sẽ lấy các cặp giá trị trục X và Y được phân tách bằng dấu phẩy để tạo hình dạng tuỳ chỉnh.
.circle {
clip-path: circle(50%);
}
.polygon {
clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
}
Tương tự như polygon()
, cũng có một hàm path()
lấy quy tắc tô màu SVG làm đối số.
Điều này cho phép các hình dạng phức tạp cao có thể được vẽ trong một công cụ đồ hoạ như Illustrator hoặc Inkscape, sau đó sao chép vào CSS.
Biến đổi
Cuối cùng trong phần tổng quan này về các hàm CSS là các hàm biến đổi, giúp làm lệch, đổi kích thước và thậm chí thay đổi chiều sâu của một phần tử.
Tất cả các hàm sau đây đều được sử dụng với thuộc tính transform
.
Xoay
Bạn có thể xoay một phần tử bằng cách sử dụng hàm rotate()
. Hàm này sẽ xoay một phần tử trên trục tâm của phần tử đó.
Bạn cũng có thể sử dụng các hàm rotateX()
, rotateY()
và rotateZ()
để xoay một phần tử trên một trục cụ thể.
Bạn có thể truyền các đơn vị độ, vòng quay và radian để xác định mức độ xoay.
.my-element {
transform: rotateX(10deg) rotateY(10deg) rotateZ(10deg);
}
Hàm rotate3d()
nhận 4 đối số.
3 đối số đầu tiên là các số, xác định toạ độ X, Y và Z. Đối số thứ tư là độ xoay, giống như các hàm xoay khác, chấp nhận độ, góc và vòng quay.
.my-element {
transform: rotate3d(1, 1, 1, 10deg);
}
Tỷ lệ
Bạn có thể thay đổi tỷ lệ của một phần tử bằng transform
và hàm scale()
.
Hàm này chấp nhận một hoặc hai số làm giá trị xác định tỷ lệ dương hoặc âm.
Nếu bạn chỉ xác định một đối số số, cả trục X và Y sẽ được điều chỉnh theo cùng một tỷ lệ và việc xác định cả hai là viết tắt của X và Y.
Tương tự như rotate()
, có các hàm scaleX()
, scaleY()
và scaleZ()
để điều chỉnh tỷ lệ một phần tử trên một trục cụ thể.
.my-element {
transform: scaleX(1.2) scaleY(1.2);
}
Cũng giống như hàm rotate
, có một hàm scale3d()
.
Hàm này tương tự như scale()
, nhưng có 3 đối số: hệ số tỷ lệ X, Y và Z.
Dịch
Hàm translate()
di chuyển một phần tử trong khi vẫn duy trì vị trí của phần tử đó trong luồng tài liệu.
Các phương thức này chấp nhận giá trị độ dài và tỷ lệ phần trăm làm đối số.
Hàm translate()
dịch một phần tử dọc theo trục X nếu bạn xác định một đối số và dịch một phần tử dọc theo trục X và Y nếu bạn xác định cả hai đối số.
.my-element {
transform: translatex(40px) translatey(25px);
}
Bạn có thể – giống như với các hàm biến đổi khác – sử dụng các hàm cụ thể cho một trục cụ thể, bằng cách sử dụng translateX
, translateY
và translateZ
.
Bạn cũng có thể sử dụng translate3d
để xác định phép dịch X, Y và Z trong một hàm.
Độ lệch
Bạn có thể làm xiên một phần tử bằng cách sử dụng các hàm skew()
chấp nhận các góc làm đối số.
Hàm skew()
hoạt động rất giống với translate()
.
Nếu bạn chỉ xác định một đối số, thì đối số đó sẽ chỉ ảnh hưởng đến trục X và nếu bạn xác định cả hai đối số, thì đối số đó sẽ ảnh hưởng đến trục X và Y.
Bạn cũng có thể sử dụng skewX
và skewY
để ảnh hưởng độc lập đến từng trục.
.my-element {
transform: skew(10deg);
}
Phối cảnh
Cuối cùng, bạn có thể sử dụng thuộc tính perspective
– thuộc nhóm thuộc tính biến đổi – để thay đổi khoảng cách giữa người dùng và mặt phẳng Z.
Điều này tạo cảm giác về khoảng cách và có thể được dùng để tạo độ sâu trường trong thiết kế.
Ví dụ này của David Desandro, trong bài viết rất hữu ích của họ, cho thấy cách sử dụng thuộc tính này, cùng với các thuộc tính perspective-origin-x
và perspective-origin-y
để tạo trải nghiệm thực sự 3D.
Hàm ảnh động, độ dốc và bộ lọc
CSS cũng cung cấp các hàm giúp bạn tạo ảnh động cho các phần tử, áp dụng độ dốc cho các phần tử đó và sử dụng bộ lọc đồ hoạ để điều chỉnh giao diện của các phần tử đó. Để giữ cho mô-đun này ngắn gọn nhất có thể, chúng sẽ được đề cập trong các mô-đun được liên kết. Tất cả đều tuân theo cấu trúc tương tự như các hàm được minh hoạ trong mô-đun này.
Kiểm tra mức độ hiểu biết
Kiểm tra kiến thức của bạn về hàm
Bạn có thể xác định các hàm CSS bằng ký tự nào?
[]
:
{}
()
::
CSS có tích hợp hàm toán học không?
Bạn có thể đặt một hàm calc()
bên trong một calc()
khác như font-size: calc(10px + calc(5px * 3));
Đối số nào sau đây hợp lệ cho sin()
và cos()
?
10deg
pi
5em
45
Hàm nào sau đây là hàm hình dạng CSS?
rect()
circle()
inset()
polygon()
square()
ellipse()