Cú pháp CSS khá đơn giản. Tuy nhiên, nhiều nguyên tắc cơ bản trong cách hoạt động của nó thường khiến người dùng bất ngờ. Điều này có thể dẫn đến sự bối rối và thất vọng lớn. Cũng có những lúc có nhiều cách để thực hiện cùng một việc. Điều đó cũng gây thêm sự thất vọng vì bạn không biết cách nào tốt hơn trong tình huống cụ thể. CSS thực sự là một trong những thứ mà khi mới bắt đầu, nó có vẻ là điều dễ dàng nhất trên đời. Nhưng nó có thể nhanh chóng dẫn đến những lúc bạn chỉ muốn ném máy tính ra ngoài cửa sổ. Vì vậy, hãy xem xét tám khái niệm CSS cực kỳ quan trọng. Khi bạn hiểu chúng, mọi thứ có thể trở nên đơn giản hơn và cuộc sống của bạn sẽ dễ dàng hơn nhiều khi viết CSS.
1. Mô hình hộp (Box Model) và lý do bạn cần box-sizing: border-box
Đây là một trong những điều thực sự quan trọng cần làm trong mọi tệp bạn từng làm việc. Hãy bắt đầu CSS của bạn với đoạn mã sau:
* {
box-sizing: border-box;
}Bộ chọn dấu sao (*) có nghĩa là “chọn mọi thứ”. Theo thời gian, bạn cũng sẽ bắt đầu sử dụng các phần tử giả (pseudo-elements). Đừng lo lắng nếu bạn chưa biết chúng là gì; chúng ta sẽ nói về chúng sau. Khi đó, bạn sẽ muốn cập nhật đoạn mã trên thành:
*, *::before, *::after {
box-sizing: border-box;
}Hãy tạo thói quen đưa các phần tử giả vào ngay bây giờ, ngay cả khi bạn chưa sử dụng chúng. Bạn sẽ cần chúng cuối cùng.
Đây là lý do tại sao điều này quan trọng. Giả sử bạn có một phần tử và bạn đặt chiều rộng của nó là 400 pixel và lề đệm (padding) là 20 pixel. Hành vi mặc định (gọi là content-box) có nghĩa là chiều rộng chỉ là nội dung đó. Vì vậy, bạn đang thêm 20 pixel ở bên trái và 20 pixel ở bên phải vào trên 400 pixel đó. Phần tử của bạn thực sự rộng 440 pixel bây giờ.
Với box-sizing: border-box, 400 pixel đó bao gồm cả lề đệm. Lề đệm đẩy vào bên trong, và phần tử vẫn rộng 400 pixel. Điều này giúp việc tính toán dễ dàng hơn nhiều. Nó cũng giúp bạn thực sự có thể ước tính kích thước của một cái gì đó. Điều này không còn quan trọng như trước đây khi chúng ta có bố cục dựa trên float và chiều rộng, chiều cao phổ biến hơn.
Tuy nhiên, vẫn có những trường hợp chúng ta đặt chiều rộng rõ ràng. Điều này sẽ giúp bạn tiết kiệm rất nhiều rắc rối về lâu dài. Hãy tạo thói quen đặt đoạn mã này ở đầu mỗi tệp CSS bạn tạo.
2. Độ đặc hiệu (Specificity) – Lý do các kiểu của bạn không hoạt động
Độ đặc hiệu là mức độ cụ thể của các bộ chọn trong CSS của chúng ta. Đây có lẽ là lý do số một khiến người mới bắt đầu thất vọng khi các kiểu của họ không được áp dụng.
Thường có ba cấp độ bộ chọn:
- Bộ chọn phần tử (độ đặc hiệu thấp nhất):
h2 { color: red; } - Bộ chọn lớp (độ đặc hiệu trung bình):
.color-accent { color: purple; } - Bộ chọn ID (độ đặc hiệu cao nhất):
#example { color: lime; }
Vấn đề là: ngay cả khi bạn có một bộ chọn h2 ở phía dưới tệp CSS của bạn nói rằng màu sắc phải là đỏ.
Nếu h2 đó có một lớp với màu khác, lớp đó sẽ thắng. Vị trí của nó trong cascade không quan trọng. Một bộ chọn lớp có tầm quan trọng cao hơn một bộ chọn phần tử. Điều tương tự cũng áp dụng cho ID.
Một bộ chọn ID sẽ luôn thắng một bộ chọn lớp.
Một bộ chọn lớp sẽ luôn thắng một bộ chọn phần tử.
Bạn cũng có thể tăng độ đặc hiệu bằng các bộ chọn con cháu (descendant selectors).
Ví dụ:
.dark-background h3 {
color: red;
}Điều này cụ thể hơn chỉ h3.
Lý do là vì nó là sự kết hợp của bộ chọn lớp và bộ chọn phần tử.
Khi có điều gì đó không hoạt động, các công cụ phát triển (dev tools) của bạn có thể thực sự giúp ích.
Nhấp chuột phải vào phần tử, kiểm tra nó.
Bạn sẽ thấy tất cả các kiểu đang được áp dụng.
Những kiểu bị gạch bỏ đang bị ghi đè.
Bạn có thể thấy chính xác lý do tại sao, bộ chọn nào đang thắng và nó đến từ đâu trong tệp CSS của bạn.
Nói chung, hãy cố gắng tránh lồng ghép quá nhiều và các bộ chọn quá cụ thể.
Nhiều hệ thống thiết kế sử dụng các bộ chọn lớp đơn vì lý do chính đáng.
Chúng giữ cho độ đặc hiệu dễ quản lý và dễ dự đoán.
3. Kế thừa (Inheritance) – Viết ít CSS hơn bằng cách để mọi thứ chảy xuống
Kế thừa là khi các thuộc tính được truyền từ một phần tử cha xuống các phần tử con và cháu của nó.
Đây là một trong những điều bạn nghe nói đến sớm nhưng sau đó lại quên mất hoặc không thực sự hiểu ý nghĩa của nó.
Điểm mấu chốt là: bất cứ thứ gì liên quan đến kiểu chữ đều kế thừa theo mặc định.
Điều này bao gồm color, font-family, font-size, text-align, line-height, v.v.
Bất cứ thứ gì không liên quan đến kiểu chữ nói chung không kế thừa.
Điều này có nghĩa là bạn có thể đặt kiểu một lần trên phần tử body (hoặc html).
Chúng sẽ chảy xuống mọi thứ bên trong:
body {
color: #333;
font-size: 1.25rem;
font-family: Arial, sans-serif;
}Bây giờ tất cả các đoạn văn, tiêu đề và các phần tử văn bản khác của bạn sẽ kế thừa các kiểu này.
Bạn không cần phải chọn từng cái một.
Ưu điểm lớn ở đây là bạn viết ít mã hơn rất nhiều.
Bạn đặt nó một lần và sau đó bạn không phải lo lắng về nó nữa.
Tất nhiên, bạn luôn có thể ghi đè mọi thứ bằng các bộ chọn cụ thể hơn khi cần.
Một lưu ý nhanh: các phần tử biểu mẫu thực sự không kế thừa các thuộc tính phông chữ như bạn mong đợi.
Bạn thường thấy điều này trong các thiết lập lại CSS (CSS resets):
button, input, textarea, select {
font: inherit;
}Điều này buộc các phần tử này bắt đầu kế thừa tất cả các thuộc tính phông chữ như bạn mong đợi ngay từ đầu.
font: inherit; là một cách viết tắt.
Nó kế thừa font-family, font-size, font-weight, line-height và tất cả các thuộc tính liên quan đến phông chữ khác cùng một lúc.
Càng nhiều càng tốt, hãy dựa vào tính kế thừa.
Nó có nghĩa là bạn viết ít mã hơn rất nhiều.
Bạn có thể chọn những nơi bạn muốn phá vỡ quy tắc đó.
Một trong những sai lầm mà mọi người mắc phải là họ bắt đầu chọn mọi thứ và cố gắng tạo kiểu cho từng cái một.
Điều đó chỉ tạo ra nhiều công việc hơn cho bạn.
4. Đơn vị CSS (CSS Units) – Chọn kích thước phù hợp cho công việc
Hiểu các đơn vị khác nhau là nền tảng để tạo ra các bố cục hoạt động trên các kích thước màn hình và tình huống khác nhau.
Có rất nhiều đơn vị khác nhau trong CSS.
Biết cách sử dụng đơn vị nào có thể gây nhầm lẫn.
- Đơn vị tuyệt đối:
px– Pixel là đơn vị cố định. Tốt cho viền và các phép đo nhỏ, chính xác. Không tốt cho thiết kế đáp ứng khi dùng cho bố cục.
- Đơn vị tương đối:
%– Phần trăm kích thước của phần tử cha. Rất tốt cho chiều rộng.em– Tương đối vớifont-sizecủa chính phần tử đó. Cộng dồn khi lồng nhau (có thể phức tạp).rem– Tương đối vớifont-sizegốc (html). Không cộng dồn, giúp dễ dự đoán hơn. Rất tốt cho khoảng cách và kích thước phông chữ.vw/vh– Chiều rộng và chiều cao của khung nhìn (viewport).1vwlà 1% chiều rộng khung nhìn. Rất tốt cho các phần toàn màn hình.
Đối với người mới bắt đầu, đây là một điểm khởi đầu đơn giản:
- Sử dụng
remcho kích thước phông chữ và khoảng cách (padding, margin). - Sử dụng
%hoặcfr(trong grid) cho chiều rộng. - Sử dụng
pxcho những thứ nhỏ như viền. - Sử dụng
vw/vhkhi bạn cần thứ gì đó tương đối với khung nhìn.
Lý do rem rất phổ biến là vì nếu người dùng thay đổi kích thước phông chữ mặc định của trình duyệt (để dễ tiếp cận), mọi thứ sẽ tự động điều chỉnh theo tỷ lệ.
Nếu bạn sử dụng px ở khắp mọi nơi, không có gì sẽ điều chỉnh.
Bạn không cần phải ghi nhớ tất cả điều này ngay lập tức.
Hãy bắt đầu với rem cho hầu hết mọi thứ và px cho viền, và bạn sẽ ổn.
Khi bạn cảm thấy thoải mái hơn, bạn có thể thử nghiệm với các đơn vị khác.
5. Thuộc tính Display (Display Property) – Cách các phần tử thực sự hoạt động
Thuộc tính display là nền tảng để hiểu cách các phần tử hoạt động trên trang.
Mỗi phần tử HTML có một giá trị display mặc định.
Hiểu điều này là rất quan trọng.
display: block- Các phần tử khối chiếm toàn bộ chiều rộng có sẵn.
- Chúng bắt đầu trên một dòng mới.
- Hãy nghĩ đến các thẻ
div, đoạn văn, tiêu đề; chúng xếp chồng theo chiều dọc. - Bạn có thể đặt
widthvàheightcho các phần tử khối.
display: inline- Các phần tử nội tuyến chỉ chiếm nhiều chiều rộng khi cần.
- Chúng không bắt đầu trên một dòng mới.
- Hãy nghĩ đến các thẻ
span, liên kết, thẻstrong; chúng chảy trong văn bản. - Bạn không thể đặt
widthvàheightcho các phần tử nội tuyến.
display: inline-block- Đây là một dạng lai.
- Nó chảy nội tuyến như một phần tử nội tuyến.
- Tuy nhiên, bạn có thể đặt
widthvàheightcho nó như một phần tử khối. - Rất hữu ích cho những thứ như các mục điều hướng hoặc nút cần nằm cạnh nhau nhưng có kích thước cụ thể.
display: none- Điều này loại bỏ phần tử khỏi trang hoàn toàn.
- Nó không chiếm bất kỳ không gian nào.
- Khác với
visibility: hidden, cái này ẩn đi nhưng để lại một khoảng trống nơi nó sẽ ở.
display: flexvàdisplay: grid- Đây là những công cụ bố cục mạnh mẽ của bạn.
- Chúng ta sẽ nói thêm về chúng trong phần tiếp theo.
Hiểu display rất quan trọng vì đôi khi bạn cần thay đổi hành vi mặc định của một phần tử.
Có thể bạn muốn một liên kết hoạt động như một khối để bạn có thể cho nó padding và làm cho nó dễ nhấp hơn.
Hoặc bạn muốn các mục danh sách nằm cạnh nhau thay vì xếp chồng lên nhau.
6. Bố cục với Flexbox và Grid (Không phải Định vị!)
Khi bạn xây dựng bố cục, bạn sẽ muốn chọn giữa Flexbox hoặc Grid.
Nếu bạn chưa học cái nào trong số chúng, bạn sẽ muốn học cả hai.
Đây là khuyến nghị của tôi: hãy bắt đầu với Grid.
Nó dễ hiểu hơn khi bạn mới bắt đầu.
Nó mang lại cho bạn nhiều quyền kiểm soát hơn để xây dựng bố cục trang.
Lý do nên dùng Grid cho bố cục:
.columns {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}Chỉ vậy thôi.
Bạn có ba cột bằng nhau với khoảng cách giữa chúng.
Đơn vị fr là một phần của không gian có sẵn – một phần cho mỗi cột.
Nó linh hoạt và đáp ứng theo mặc định.
Lý do Flexbox cũng quan trọng: Flexbox tuyệt vời cho bố cục cấp độ thành phần.
Ví dụ như thanh điều hướng, thẻ, căn giữa nội dung, phân bổ khoảng cách đều.
Khi bạn đã quen với các nguyên tắc cơ bản của Grid, hãy thêm Flexbox vào bộ công cụ của bạn.
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}Điều cần tránh: Không sử dụng định vị (position: absolute, position: fixed) cho bố cục.
Định vị dùng cho các điều chỉnh nhỏ và các mẫu UI cụ thể, không phải để xây dựng cấu trúc trang chính của bạn.
Bạn học position absolute, đặt chiều rộng và chiều cao, đặt nó ở nơi bạn muốn.
Đó là cách tồi tệ nhất có thể để xây dựng một bố cục.
Bạn cũng có thể thấy các hướng dẫn cũ với float.
Nếu bạn thấy những điều liên quan đến việc xây dựng bố cục bằng float, hãy hoàn toàn tránh nó.
Float là một thủ thuật chúng ta đã sử dụng trước khi flexbox và grid tồn tại.
Tất cả các bố cục hiện đại đều được xây dựng bằng flexbox hoặc grid.
Ngày nay chúng ta không cần đặt chiều rộng nhiều.
Lý do là vì vùng chứa cha (parent container) làm tất cả công việc cho chúng ta.
Bạn thiết lập grid hoặc flex container.
Các phần tử con chỉ vừa vặn vào không gian được cấp cho chúng.
7. Pseudo-classes và Pseudo-elements – Tạo sự tương tác
Pseudo-classes và pseudo-elements là những công cụ cực kỳ mạnh mẽ.
Chúng cho phép bạn tạo kiểu cho các phần tử dựa trên trạng thái của chúng.
Hoặc chúng cho phép bạn thêm nội dung mà không cần chạm vào HTML của bạn.
Chúng trông tương tự nhau nhưng thực hiện những việc khác nhau.
Cách bạn viết chúng cũng hơi khác một chút.
- Pseudo-classes sử dụng một dấu hai chấm đơn (
:) và tất cả là về trạng thái. Chúng cho phép bạn tạo kiểu cho các phần tử khi có điều gì đó xảy ra với chúng:a:hover { color: blue; text-decoration: underline; }button:focus { outline: 2px solid blue; }input:invalid { border-color: red; }li:first-child { font-weight: bold; }
Đây là những điều cần thiết để tạo ra trải nghiệm tương tác.
Các liên kết của bạn cần trạng thái di chuột (hover states).
Các trường nhập biểu mẫu của bạn cần kiểu tập trung (focus styles) để dễ tiếp cận.
Bạn thường muốn tạo kiểu cho mục đầu tiên hoặc cuối cùng trong danh sách khác nhau.
- Pseudo-elements sử dụng dấu hai chấm kép (
::) và cho phép bạn thêm nội dung trang trí hoặc tạo kiểu cho các phần cụ thể của một phần tử:.quote::before { content: '"'; font-size: 2em; color: gray; }p::first-line { font-weight: bold; }.card::after { content: ''; display: block; width: 100%; height: 3px; background: blue; margin-top: 1rem; }
Các pseudo-elements
::beforevà::afterđặc biệt hữu ích.Chúng giúp thêm các yếu tố trang trí mà không làm lộn xộn HTML của bạn.
Bạn có thể tạo biểu tượng, đường phân cách hoặc hiệu ứng hình ảnh hoàn toàn bằng CSS.
Một điều cần nhớ: pseudo-elements cần thuộc tính
contentđể hiển thị, ngay cả khi đó chỉ làcontent: ''.Nếu không có nó, chúng sẽ không hiển thị chút nào.
Và đây là lý do tại sao trong phần mô hình hộp, tôi đã bao gồm
*::beforevà*::aftertrong quy tắcbox-sizing.Pseudo-elements tạo ra các hộp thực tế trên trang.
Chúng cần hành vi
box-sizingtương tự như mọi thứ khác.Nếu bạn không bao gồm chúng, bạn có thể gặp phải các vấn đề về kích thước kỳ lạ sau này.
8. Thiết kế đáp ứng với Media Queries (Làm cho nó hoạt động ở mọi nơi)
Trang web của bạn cần hoạt động trên điện thoại, máy tính bảng, máy tính xách tay và màn hình máy tính để bàn lớn.
Đó là thực tế ngày nay.
Và cách chúng ta thực hiện điều đó là với các media queries.
Media queries cho phép bạn áp dụng các kiểu khác nhau dựa trên kích thước màn hình:
/* Phương pháp ưu tiên thiết bị di động - kiểu cho màn hình nhỏ trước */.container {
padding: 1rem;
}
/* Máy tính bảng trở lên */@media (min-width: 768px) {
.container {
padding: 2rem;
}
}
/* Máy tính để bàn trở lên */@media (min-width: 1024px) {
.container {
padding: 3rem;
max-width: 1200px;
margin: 0 auto;
}
}Tôi khuyến nghị phương pháp ưu tiên thiết bị di động (mobile-first).
Viết các kiểu cơ bản của bạn cho thiết bị di động.
Sau đó sử dụng media queries min-width để thêm độ phức tạp khi màn hình lớn hơn.
Điều này có ý nghĩa hơn vì:
- Di động là môi trường bị hạn chế nhất – nếu nó hoạt động trên di động, bạn có thể xây dựng từ đó.
- Dễ dàng thêm độ phức tạp hơn là loại bỏ nó.
- Hầu hết lưu lượng truy cập ngày nay là từ di động.
Bạn cũng có thể sử dụng media queries cho những việc khác:
- Chế độ tối (Dark mode)
@media (prefers-color-scheme: dark) { body { background: #222; color: #fff; } } - Kiểu in (Print styles)
@media print { nav, footer { display: none; } }
Các điểm ngắt (breakpoints) phổ biến bạn sẽ thấy là:
640pxhoặc768pxcho máy tính bảng.1024pxhoặc1280pxcho máy tính để bàn.
Thành thật mà nói, các điểm ngắt của bạn nên dựa trên nội dung của bạn, không phải các thiết bị cụ thể.
Đừng quá căng thẳng về việc có được các điểm ngắt hoàn hảo ngay từ đầu.
Khi bạn xây dựng, bạn sẽ thấy nơi thiết kế của bạn bị hỏng.
Đó là nơi bạn thêm một media query.
Các công cụ phát triển trình duyệt của bạn cho phép bạn kiểm tra điều này dễ dàng.
Chỉ cần bật chế độ thiết kế đáp ứng và thay đổi kích thước khung nhìn để xem mọi thứ bắt đầu trông kỳ lạ ở đâu.
Bạn không cần phải thành thạo thiết kế đáp ứng ngay lập tức.
Hãy bắt đầu bằng cách làm cho mọi thứ hoạt động trên di động.
Sau đó thêm một hoặc hai điểm ngắt khi bạn cần.
Theo thời gian, bạn sẽ cảm nhận được nơi bạn thường cần điều chỉnh mọi thứ.
Bonus: Tách biệt bố cục khỏi nội dung
Điều cuối cùng này hơi dựa trên những gì tôi vừa chỉ cho bạn về bố cục.
Càng nhiều càng tốt, hãy cố gắng tạo sự tách biệt giữa cách bạn tạo kiểu cho bố cục và chính nội dung.
Ý tôi là có các lớp thực hiện các công việc cụ thể:
- Lớp này xử lý bố cục:
/* Lớp này xử lý bố cục */.columns { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; } - Lớp này xử lý kiểu nội dung:
/* Lớp này xử lý kiểu nội dung */.card { background: #333; color: white; padding: 2rem; }
Sau đó trong HTML của bạn:
<div class="columns">
<div class="card">Nội dung ở đây</div>
<div class="card">Nội dung ở đây</div>
<div class="card">Nội dung ở đây</div>
</div>Lớp columns đang thiết lập cấu trúc bố cục.
Lớp card đang tạo kiểu cho nội dung bên trong bố cục đó.
Chúng có các công việc riêng biệt.
Điều này làm cho cuộc sống của bạn dễ dàng hơn rất nhiều vì:
- Dễ dàng tìm bộ chọn hơn khi bạn cần sửa đổi điều gì đó.
- Bạn ít gặp xung đột hơn với cascade và độ đặc hiệu.
- Bạn có thể tái sử dụng các lớp này trong các kết hợp khác nhau.
- Mã của bạn dễ bảo trì hơn.
Bạn thậm chí có thể áp dụng cả hai lớp cho cùng một phần tử nếu cần:
<div class="columns card">Điểm mấu chốt là mỗi lớp có một công việc cụ thể.
Điều đó làm cho mọi thứ dễ dự đoán hơn và dễ làm việc hơn.
Tám khái niệm này – mô hình hộp, độ đặc hiệu, kế thừa, đơn vị CSS, thuộc tính display, bố cục hiện đại, pseudo-classes và pseudo-elements, và thiết kế đáp ứng – tạo thành nền tảng của việc viết CSS tốt.
Khi bạn hiểu cách chúng hoạt động cùng nhau, CSS sẽ không còn cảm thấy như phép thuật (hoặc một nguồn gây thất vọng) nữa.
Nó bắt đầu có ý nghĩa logic.
Bạn không cần phải thành thạo tất cả những điều này cùng một lúc.
Hãy bắt đầu với một cái, làm quen với nó, và chuyển sang cái tiếp theo.
Nhưng việc hiểu những nguyên tắc cơ bản này sẽ giúp bạn tiết kiệm vô số giờ gỡ lỗi.
Nó cũng sẽ giúp bạn tự tin hơn rất nhiều khi viết CSS.
Tham khảo: medium.com

Bài viết liên quan: