11/08/2018, 21:26

Nguy hiểm cực cơ bản nhưng ít đề phòng khi lựa chọn element để định dạng CSS

Chúng ta đã biết #id trong CSS là để chỉ đích danh một element, nó giống như số chứng minh thư của bạn, mỗi người xài một cái, không có hai người nào có chung số CMT. Còn .class thì khác, nó để nhóm những element có đặc điểm chung để xử lý luôn một chùm. Nó giống như sở thích của bạn. ...

Chúng ta đã biết #id trong CSS là để chỉ đích danh một element, nó giống như số chứng minh thư của bạn, mỗi người xài một cái, không có hai người nào có chung số CMT.

Còn .class thì khác, nó để nhóm những element có đặc điểm chung để xử lý luôn một chùm. Nó giống như sở thích của bạn. Bạn thích uống bia, anh trai bạn thích uống sữa. Đương nhiên bạn vừa có thể thích uống bia và thích uống sữa mà. Và đương nhiên ngoài bạn ra thì người khác cũng có quyền thích uống bia chứ. Như vậy một người có thể có nhiều sở thích, và một sở thích có thể được yêu thích bởi nhiều người.

Như một lẽ đương nhiên, khi bạn có một element duy nhất, ví dụ ảnh bìa, cả trang web của bạn chỉ có duy nhất một chỗ đặt ảnh bìa thôi, thì bạn sẽ nghĩ đến việc đặt ID cho nó, tạm gọi là#anhbia.

Vì đã sẵn rồi nên khi định dạng CSS cho cái ảnh bìa đó bạn túm luôn cái #anhbia này

#anhbia{
    height: 900px;
 }

Tiếp theo bạn định dạng thêm một lô lốc các ảnh khác trong trang, mỗi cái một kiểu.

Cuối cùng bạn thiết kế phiên bản di động (sử dụng media query). Ở bản di động này, bạn muốn tất cả các ảnh có chiều dài bé thôi, 300px chẳng hạn. Lúc này bạn thấy tất cả các ảnh có chung một định dạng là height: 300px nên bạn sẽ quay lại HTML để chèn class = "hinhanh" vào tất cả các hình ảnh trong trang của bạn. Rồi vào css:

 .hinhanh{
    height: 300px;
  }

Bạn mong chờ kết quả hiện ra, và rồi những hình ảnh bình thường đều đã được co lại cho bé đi, riêng cái ảnh bìa vẫn lừng lững to đùng đứng đó. Tại sao?!

Tại vì ID có quyền ưu tiên hơn class

Nên css của #anhbia đã đè lên css của .hinhanh, kể cả khi css của class được viết sau hoặc nằm trong media query, kể cả khi element không phải là một ID mà chỉ là một đứa con cháu của ID thì cũng vẫn đè lên class.

ID quả thật cứng đầu và ghê gớm, to đến nỗi ngay cả con cháu chúng nó cũng đè đầu cưỡi cổ mình được :laughing:

Hậu quả hết sức tràn trề, đặc biệt là khi bạn đã định dạng css cho rất nhiều ID khác nhau và cả lũ con cháu chúng nó, và bây giờ phải đi giải quyết từng đứa một. Cách giải quyết có hai hướng:

  1. Chỉ đích danh ID từng đứa rồi cho chúng một chiều dài mới.
  2. Đổi ID của chúng sang class cùng tên, ví dụ từ #anhbia thành .anhbia, khi nó chỉ là class thì sẽ hết cứng đầu và class .hinhanh viết sau sẽ có tác dụng

Cả hai cách giải quyết đều có khả năng làm trụi hết tóc của bạn, vậy nên tốt nhất là ngay từ đầu không định dạng css cho id mà hãy đặt class và định dạng class.

Một số thứ tự ưu tiên cơ bản, viết theo thứ tự giảm dần, từ ưu tiên cao tới ưu tiên thấp

  • ID > class > thẻ html
  • inline css viết trong file html > css viết trong file css
  • đích danh > kế thừa
  • viết sau > viết trước

Đọc thêm về CSS Specificity

Child combinator là sử dụng dấu > để lựa chọn con của một element, ví dụ sau đây là lựa chọn các link nằm ngay bên trong chân trang

footer > a{
    color: red
    }

Descendant combinator là sử dụng dấu cách để lựa chọn con cháu chắt... của một element, ví dụ sau đây lựa chọn các link nằm trong chân trang, dù link này thực ra nằm bên trong một đoạn văn rồi đoạn văn này nằm bên trong chân trang thì cũng ok.

footer a{
    color: red
}

Tại sao nó lại nguy hiểm?

Vì khi thay đổi vị trí các element trong html là định dạng css của các element này hỏng hết

Bạn bưng cái link ra khỏi chân trang vì bạn không thích nó nằm ở đó nữa, vô tình cái link không còn là con cháu của chân trang, và mọi css đã viết cho nó sẽ không còn nhận ra nó là ai.

Cách giải quyết là đổi tên cha mẹ cho nó trong file css thôi, ví dụ bạn chuyển nó qua header thì đổi sang header > a

Nếu file html bị xáo trộn nhiều, thì việc đổi tên cha mẹ cho hàng chục hàng trăm đứa trẻ quả thực không đơn giản. Giải pháp là đặt tên class cho element ngay từ đầu và dùng class để định dạng css

.redlink{
    color: red;
}

Như vậy thì dù là con cháu của ai thì vẫn sẽ màu đỏ thôi :laughing:
Đọc thêm về selector combinator

Nếu có một selector là footer > a, bạn nghĩ trình duyệt sẽ đi tìm footer trước, rồi trong footer nó sẽ lùng sục a đúng không? Sự thật thì ngược lại. Nó đi tìm tất cả các a trong cả cái trang web trước, rồi nó tìm xem cái a nào có bố là footer.

Vậy nên nếu bạn chọn footer>div (chọn div con của footer) thì trình duyệt sẽ phải tìm tất cả các div trong trang. Hoặc tệ hơn là footer>* (chọn tất cả những gì bên trong footer, * nghĩa là tất cả) trình duyệt sẽ tìm tất cả mọi element trong trang. Thật kinh khủng.

Vậy nên hãy tránh dùng những đứa con là element quả phổ biến như div, a, p, img... mà thay vào đó hãy dùng class.

0