Kể từ khi được đề xuất vào năm 1994 và phát hành lần đầu vào năm 1996 tại CERN, cái nôi của Web, Cascading Style Sheets [CSS] đã phát triển từ một mô tả tĩnh về các kiểu đơn giản thành nền tảng của thiết kế web hiện đại.
Ngay cả vào năm 1996, khái niệm biểu định kiểu không phải là một ý tưởng mới. Chúng đã tồn tại ở một số khả năng kể từ Ngôn ngữ đánh dấu tổng quát hóa tiêu chuẩn [SGML], nhưng chúng không được sử dụng cho web. Bộ tính năng khá hạn chế so với ngày nay
- Màu sắc
- Thuộc tính phông chữ và kiểu chữ
- Thuộc tính văn bản [e. g. , khoảng cách từ/chữ cái]
- Thuộc tính liên quan đến cạnh [e. g. , lề, phần đệm, đường viền]
- căn chỉnh
Đó là người kế nhiệm thực sự đầu tiên, CSS 2. 1, trở thành Đề xuất Ứng viên W3C năm 2004. Sau bảy năm nữa, nó cuối cùng đã trở thành Khuyến nghị của W3C vào năm 2011, mặc dù trước đó nó đã được sử dụng và triển khai thông qua trình duyệt.
Mặc dù CSS 2 đã tồn tại nhưng 2. Bản phát hành số 1 đã tinh chỉnh nó bằng cách loại bỏ các tính năng được hỗ trợ kém hoặc bị cộng đồng từ chối và bao gồm các tính năng đã được triển khai bởi các trình duyệt
Từ năm 1999, phiên bản tiếp theo, CSS 3, được phát triển. Nó đã giới thiệu khái niệm về các mô-đun để hiểu rõ hơn và phân tách đặc tả CSS. Một số mô-đun của nó vẫn đang hoạt động ở dạng nháp, thậm chí còn được cho là đã được sử dụng rộng rãi. Và web sẽ không giống như vậy nếu không có chúng
- Bộ chọn cấp 3 [e. g. , bộ chọn thuộc tính.
6]html { --default-margin: 1rem; } .my-class { margin: var[--default-margin]; }
- Bố cục hộp linh hoạt [flexbox]
- Truy vấn phương tiện truyền thông
- Nền và đường viền được cải thiện
- Nhiều hệ thống màu sắc hơn [e. g. , rgba, hsl, hsla, độ dốc]
- …và nhiều hơn nữa
Cần một giải pháp linh hoạt hơn
CSS được dự định sử dụng để mô tả cách trình bày nội dung trang web, không phải là ngôn ngữ lập trình. Các tính năng động khá hạn chế
Sử dụng lại các kiểu và tạo bộ chọn cơ sở thường có nghĩa là sao chép hoặc thay đổi mối quan hệ cha-con, điều này có thể ảnh hưởng đến tính đặc hiệu của bộ chọn. Không hỗ trợ cho các lớp cơ sở hoặc biến có nghĩa là các thay đổi có thể ảnh hưởng đến toàn bộ [các] tệp CSS, khiến bạn dễ bỏ sót điều gì đó nếu yêu cầu thay đổi
Để khắc phục những thiếu sót này, các bộ tiền xử lý CSS đã được tạo ra, đáng chú ý nhất là SASS/SCSS, LESS, Stylus và PostCSS
Tất cả các bộ tiền xử lý này đang cố gắng cải thiện UX của các nhà phát triển CSS bằng cách cung cấp các tính năng mới, đôi khi theo cú pháp giống như CSS [e. g. , SCSS, Less, PostCSS], đôi khi có cú pháp “cải tiến” [e. g. , Sass, Bút cảm ứng]. Bằng cách chuyển đổi CSS thành ngôn ngữ lập trình chính thức, rất nhiều tính năng động và tiện lợi sẽ khả dụng, khiến nó dễ đọc hơn và dễ bảo trì hơn
- Biến
- bộ chọn lồng nhau
- Hàm/mixin/kế thừa
- Hoạt động màu sắc [e. g. , làm tối, làm sáng, thay đổi màu sắc]
- Toán tử logic [if-else], vòng lặp
- nhập khẩu
- …và nhiều hơn nữa
Nhưng nhược điểm lớn nhất của tiền xử lý nằm ngay ở cái tên. nó cần được xử lý trước khi có thể được giao cho khách hàng. Điều này có nghĩa là chúng tôi cần một số loại đường ống nội dung hoặc ít nhất là một tác vụ cụ thể trong môi trường xây dựng của chúng tôi để xử lý CSS. Chúng không thể thay đổi linh hoạt trong thời gian chạy và không nhận thức được cấu trúc của DOM, dẫn đến các biến có phạm vi từ vựng và CSS khá tĩnh. Ngoài ra, không có tiêu chuẩn cho các bộ tiền xử lý CSS và chúng không tương thích [hoàn toàn] với nhau
Nhiều bánh răng hơn cho các dự án của chúng tôi cần được bảo trì và có thể bị hỏng
Một cách tốt hơn sẽ là một CSS năng động hơn, tương thích trực tiếp với máy khách, vì vậy không cần thực hiện thêm bước nào
Thuộc tính CSS tùy chỉnh
Vào năm 2015, mô-đun Thuộc tính tùy chỉnh CSS cho mô-đun biến xếp tầng Cấp 1 đã trở thành Đề xuất dành cho ứng viên của W3C. Mô-đun giới thiệu các biến xếp tầng được tất cả các thuộc tính CSS chấp nhận. So với bộ tiền xử lý, bộ tính năng có vẻ đơn giản, nhưng chúng vẫn có thể thực hiện nhiều việc mà bộ tiền xử lý được sử dụng cho. Chúng không nhằm mục đích sao chép một số tính năng của bộ tiền xử lý, nhưng để kích hoạt các quy trình công việc thậm chí không thể thực hiện được trước đây — ngay cả với sự trợ giúp của bộ tiền xử lý
Tuyên ngôn
Cú pháp chung cho các biến là
html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
7. Chúng phải được xác định trong bộ chọn CSS và có cùng ngữ nghĩa xếp tầng như bất kỳ thuộc tính nào khác1
2
3
4
5
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
Chúng tôi có thể sử dụng mọi giá trị thuộc tính được CSS hỗ trợ, chẳng hạn như màu sắc, kích thước,
html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
8, html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
9/1
2
3
4
5
0/1
2
3
4
5
1, v.v.Cách sử dụng
Quyền truy cập vào các biến được cấp bởi hàm
1
2
3
4
5
21
2
3
4
5
6
7
html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
Phép tính
Hàm
1
2
3
4
5
3 với tất cả các toán tử của nó [1
2
3
4
5
4, 1
2
3
4
5
5, 1
2
3
4
5
6, 1
2
3
4
5
7], cũng được hỗ trợ1
2
3
4
5
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
Phạm vi
Như đã đề cập trước đây, phạm vi của các thuộc tính tùy chỉnh được kế thừa và phân tầng theo mặc định, giống như các thuộc tính CSS tiêu chuẩn, thay vì được xác định phạm vi theo từ vựng như các biến tiền xử lý
Để tạo một biến trong phạm vi toàn cầu, có sẵn cho tất cả các hậu duệ, lớp giả _____2_______8 có thể được sử dụng
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:root {
--global-scope: 1rem;
}
.local-scope {
--local-scope: 0.2rem;
}
.local-scope .nested {
/* Can access global, and scope of .local-scope */
padding: calc[var[--global-scope] + var[--local-scope]];
}
.another-local-scope {
/* Can access global, but not scope of .local-scope */
padding: calc[var[--global-scope]];
}
Với phạm vi, chúng tôi cũng có thể xây dựng các bộ quy tắc có thể dễ dàng sửa đổi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a {
--link: black;
--link-hover: red;
--link-visited: blue;
}
a:link {
color: var[--link];
}
a:hover {
color: var[--link-hover];
}
a:visited {
color: var[--link-visited];
}
.monochrome {
--link: black;
--link-hover: black;
--link-visited: black;
}
Với
1
2
3
4
5
9 cụ thể hơn, chúng tôi có thể sửa đổi một neo và nhận bảng màu đơn sắcTruy vấn phương tiện truyền thông
Tất nhiên, phạm vi/kế thừa cũng có thể được sử dụng với các truy vấn phương tiện, giúp thiết kế đáp ứng trở nên dễ dàng
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
0html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
1Tuy nhiên, hãy cẩn thận với một hạn chế — không thể sử dụng biến cho các giá trị trong truy vấn phương tiện
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
2_______3_______3Thoạt nhìn, điều này có vẻ kỳ lạ nhưng có thể giải thích dễ dàng. Truy vấn phương tiện không phải là bộ chọn và không kế thừa bất kỳ thuộc tính nào theo tầng
Giá trị mặc định
Các giá trị mặc định được hỗ trợ và là một cách tiện lợi để sửa đổi một số bộ chọn nhất định
1
2
3
4
5
6
7
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
5Chúng tôi thậm chí không cần phải khai báo trước
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
0. Chỉ cần có một .my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
1 đang hoạt động với giá trị mặc định hợp lý và cơ hội sửa đổi giá trị đó bằng cách chỉ định lại thuộc tính trong bộ chọn khácDo tính chất xếp tầng của CSS, chúng tôi cũng có thể triển khai theo chủ đề với các giá trị mặc định và kích hoạt chúng cụ thể thông qua HTML, ngay cả ở phía máy khách
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
6html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
71
2
3
4
5
6
7
html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
9CSS nội tuyến
Các biến cũng có thể được đặt nội tuyến, đây là một cách hay để sửa đổi kiểu dáng từ bên ngoài
1
2
3
4
5
6
7
0_______9_______1Trong HTML, chúng ta có thể ghi đè lên
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
0 bằng thuộc tính .my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
3html {
--primary-color: #7B60F5;
--secondary-color: #F59560;
--font: sans-serif;
}
2_______9_______3cập nhật động
Một sự khác biệt lớn [so với tiền xử lý] là việc xử lý các thay đổi giá trị. Bộ tiền xử lý cần tính toán tất cả các giá trị trong quá trình xử lý; . Đó là lý do tại sao gán lại một giá trị sau khi sử dụng không có tác dụng
1
2
3
4
5
1
2
3
4
5
6
7
5Giá trị tầng Thuộc tính tùy chỉnh CSS thay đổi và tất cả các thuộc tính liên quan được cập nhật nhanh chóng
1
2
3
4
5
6
7
61
2
3
4
5
6
7
7Kết hợp với các kiểu nội tuyến, chúng ta có thể gán lại và tính toán lại các thuộc tính CSS một cách nhanh chóng
JavaScript
Đối tượng
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
4 cung cấp hàm .my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
5, trả về kiểu dáng hiện được tính toán của một phần tửThay đổi biến hoạt động giống như đặt thuộc tính tiêu chuẩn
1
2
3
4
5
6
7
81
2
3
4
5
6
7
9Thực hành tốt nhất
Giá trị > biến
Tốt hơn là thay đổi giá trị của một biến hơn là tạo một biến khác
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
1Thay vì giới thiệu một biến khác, chúng ta nên thay đổi biến đã tồn tại
html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
2html {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
3Nếu chúng tôi không cần khai báo tất cả các biến tại một nơi và chỉ sử dụng nó trong
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
1, thì chúng tôi có thể rút ngắn CSS hơn nữahtml {
--default-margin: 1rem;
}
.my-class {
margin: var[--default-margin];
}
4_______0_______5Các biến phải là "biến"
Không phải mọi thứ cần phải là một biến. Đừng vội vàng tối ưu hóa và biến mọi thuộc tính thành một biến được xác định trong
1
2
3
4
5
8, đề phòng trường hợp bạn có thể muốn thay đổi thuộc tính đó trong tương laiCác ứng cử viên tốt cho các biến là các thuộc tính đang thực sự thay đổi. Do các ràng buộc bên ngoài, như truy vấn phương tiện hoặc yêu cầu bên trong, như lớp giả [e. g. , trạng thái di chuột] hoặc các thành phần có thể thay đổi chủ đề
Tách mối quan tâm
Với các thuộc tính tùy chỉnh, cuối cùng chúng ta có thể tách thiết kế nội dung khỏi logic bố cục thực tế
Các truy vấn phương tiện sẽ không còn thay đổi bất kỳ thuộc tính CSS tiêu chuẩn nào nữa. Chỉ nên thay đổi các giá trị của thuộc tính tùy chỉnh
Bằng cách này, chúng ta có thể khai báo tất cả các biến và truy vấn phương tiện sửa đổi của chúng ở đầu tài liệu. Các giá trị mặc định và logic về cách các thuộc tính có thể thay đổi là những thứ đầu tiên hiển thị trong tệp. Thiết kế thực tế không có logic và có thể dễ dàng đọc được mà không có bất kỳ sự phức tạp hay ẩn chứa bất ngờ nào
Phạm vi và đặt tên
Giống như tất cả các ngôn ngữ lập trình, chúng ta phải suy nghĩ về phạm vi chúng ta muốn và những gì chúng ta thực sự cần. Một phạm vi hống hách có thể làm ô nhiễm không gian biến đổi và có tác dụng phụ. Nhưng phạm vi quá hẹp sẽ hạn chế khả năng sử dụng lại của biến
Không phải mọi thứ đều cần phải có trong
1
2
3
4
5
8. Nhưng chúng ta cần tìm vị trí tốt nhất trong cây bộ chọn xếp tầng để một biến thực hiện mục đích của nóDo tính chất xếp tầng, phạm vi thực tế có thể khác với chúng ta nghĩ. Để không vô tình ghi đè bất kỳ thuộc tính nào bằng cách sử dụng lại tên, chúng ta nên tuân thủ các quy ước đặt tên. Việc đặt tên các biến có phạm vi toàn cầu bằng chữ HOA hoặc ít nhất là bằng chữ cái đầu viết hoa, giúp bạn hiểu rõ cách sử dụng chúng
Các biến phạm vi toàn cầu cũng nên được coi là giá trị tĩnh. Nếu chúng ta cần thay đổi một giá trị toàn cầu, chúng ta có thể gán lại nó cho một biến khác trong phạm vi hẹp hơn
Hãy cẩn thận
Mọi đồ chơi mới sáng bóng đều có một số nhược điểm kèm theo. Thuộc tính tùy chỉnh CSS không khác
hỗ trợ trình duyệt
Trớ trêu thay, trình duyệt có liên quan duy nhất không hỗ trợ nó lại là trình duyệt thương mại đầu tiên thực sự hỗ trợ CSS. trình duyệt web IE
Tùy thuộc vào đối tượng mục tiêu, đây có thể là một công cụ phá vỡ thỏa thuận. Nhưng nếu chúng tôi vẫn muốn hỗ trợ Internet Explorer, thì có sẵn nhiều tùy chọn điền đầy JavaScript [, 2]
Ngoại trừ IE11, hỗ trợ trình duyệt là tuyệt vời
Thiếu tính năng
Nhiều tính năng bị thiếu trong Thuộc tính tùy chỉnh CSS so với bộ tiền xử lý. Dưới đây là các tính năng còn thiếu quan trọng nhất [theo ý kiến của tôi]
bộ chọn lồng nhau
Khả năng đọc có thể được cải thiện cao với các bộ chọn lồng nhau bằng cách trực quan hóa tốt hơn cấu trúc cây của các thành phần. Đáng buồn thay, Thuộc tính tùy chỉnh CSS vẫn là CSS và không hỗ trợ các bộ chọn lồng nhau
hỗn hợp
Một nhóm các khai báo CSS có thể được sử dụng lại trong một bộ chọn khác
Chức năng
Các bộ tiền xử lý được đóng gói với các trình trợ giúp để thao tác chuỗi, hỗ trợ các danh sách trong các biến có thể được lặp lại, v.v.
nhập khẩu
Có thể chia CSS thành nhiều tệp bằng bộ tiền xử lý, nhưng vẫn chỉ có một tệp đầu ra được tối ưu hóa duy nhất sẽ cải thiện cấu trúc của bất kỳ dự án nào. Với Thuộc tính tùy chỉnh CSS, chúng tôi cũng có thể chia CSS thành nhiều tệp nhưng cần tải chúng riêng biệt bằng các thẻ
.my-class {
--size-default: 16px;
--size-large: calc[2 * var[--size-default]];
--size-small: calc[var[--size-default] - 4px];
}
9, điều này không tốt bằng một tệp, ít nhất là không có HTTP/2Phần kết luận
Chúng ta có nên sử dụng Thuộc tính tùy chỉnh CSS thay vì Bộ tiền xử lý CSS không?
Có thể tránh đường ống nội dung cho CSS là điều tuyệt vời. Có ít thứ có thể bị hỏng hơn, nhưng chúng tôi bỏ lỡ một số tính năng tuyệt vời. Mặt khác, chúng tôi có được kiểu dáng động phía máy khách mạnh mẽ, điều không thể thực hiện được với bộ tiền xử lý và kiểu dáng này sẽ tương thích với các bổ sung CSS trong tương lai
Tôi không khuyên bạn nên thay thế bất kỳ kiểu được xử lý trước nào bằng các thuộc tính tùy chỉnh chỉ vì chúng tôi có thể. Nhưng thay vào đó, hãy nghĩ đến việc thử sức trong một dự án mới. Trộn cả hai cách xử lý CSS có thể tạo ra các loại vấn đề mới và nên tránh hoặc ít nhất là tách biệt cho phù hợp
Ví dụ: một trong các dự án của chúng tôi sử dụng đường dẫn SASS tùy chỉnh để sửa đổi nhiều phiên bản Bootstrap một cách nhanh chóng bằng cách biên dịch các tệp SASS nguồn với các biến đã sửa đổi để tạo các chủ đề liên quan đến dự án. Nếu chúng tôi phải làm lại dự án với Thuộc tính tùy chỉnh CSS, chúng tôi sẽ vẫn sử dụng SASS cho Bootstrap, nhưng sẽ cố gắng sử dụng Thuộc tính tùy chỉnh CSS cho bất kỳ thành phần nào mới được phát triển
Đó không phải là Thuộc tính tùy chỉnh CSS so với. bộ tiền xử lý CSS. Chọn công cụ của bạn một cách khôn ngoan. Cả hai đều có lý do để tồn tại mà không hoàn toàn phù hợp. Vì vậy, sử dụng cả hai cho các khía cạnh khác nhau có thể là một giải pháp khả thi