All Posts
01-05-2024
06-11-2022
03-03-2022
12-01-2022
02-01-2022
20-11-2021
07-11-2021
31-10-2021
31-10-2021
02-01-2022
Ngoài những thuộc tính hay được sử dụng (display, font-size, color,...), có một số thuộc tính thỉnh thoảng mới sử dụng một lần. Đôi khi nhiều người không biết đến chúng nên dẫn tới solution CSS của các bạn sẽ phức tạp hơn. Dưới đây là một vài ghi chú/giải thích về một số thuộc tính đó.
Chúng ta có box-sizing để thiết lập thuộc tính height/width của một phần tử tính từ border vào hay từ content vào.
Tương tự như border-box, chúng ta có thuộc tính background-origin
để thiết lập vùng hiển thị của background-image
.
Thuộc tính này có 3 giá trị là: border-box
, padding-box
và content-box
tương ứng với vùng hiển thị như tên giá trị của chúng. Giá trị mặc định là padding-box
.
<div class="container"> <div>border box</div> <div>padding box</div> <div>content box</div></div>
.container { border: 2px solid green;}.container div { border: 5px solid transparent; padding: 5px; margin-top: 16px; background-image: linear-gradient(to right, red, yellow); background-repeat: no-repeat; background-color: blue;}div:nth-child(1) { background-origin: border-box;}div:nth-child(2) { background-origin: padding-box;}div:nth-child(3) { background-origin: content-box;}
Nếu giá trị của background-attachment
là fixed
thì giá trị của background-origin
sẽ bị bỏ qua.
Tương tự như background-origin, chúng ta có thêm background-clip nhưng áp dụng cho cả background-color (background-origin chỉ áp dụng cho background-image).
Tuy nhiên, nó chỉ hỗ trợ để clip background, tức là cắt gọt khu vực background hiển thị chứ không phải thiết lập như background-origin, nên không thể thay thế background-origin được.
(Nếu muốn sử dụng background-clip full chức năng với background-image, chúng ta nên set background-origin: border-box, như vậy vùng hiển thị của image sẽ full để chúng ta có thể clip)
Đây là một thuộc tính khá thông dụng. Tuy nhiên background-position với giá trị là % thì có phần hơi đặc biệt và cần note lại.
<div class="bg-percentage"></div>
.bg-percentage { height: 300px; background-image: linear-gradient(to right, red, yellow); background-size: 50% 100%; background-position: 25% 25%; background-repeat: no-repeat; border: 1px solid green;}
Nếu theo logic thông thường, chúng ta có thể nghĩ rằng vị trí của background image sẽ cách top của phần tử 25% và cách left 25%. Nhưng như demo phía trên, nó không hoạt động như vậy.
Đầu tiên nó sẽ tìm một điểm của phần tử mà vị trí đúng như background position, như ví dụ ở trên là 25% theo trục dọc và 25% theo trục ngang.
Tiếp theo, nó cũng sẽ tìm một điểm trong chính background image đó với vị trí như vậy, 25% theo trục dọc và 25% theo trục ngang.
Cuối cùng, nó sẽ dịch chuyển background image để 2 điểm đó trùng nhau. Chúng ta có hình minh họa phía dưới.
Và chúng ta có 2 điểm 25% 25% của phần tử và background image của nó trùng nhau.
Thuộc tính này rất hữu dụng khi sử dụng kèm z-index
. Nó sẽ tạo một lớp stacking context mới cho phần tử.
Dưới đây là ví dụ mình thường dùng nhất trong các project, đó là sử dụng img như background.
<div class="container"> <img src="/images/bg.jpeg" /> <h1>This is a title</h1></div>
.container { position: relative; height: 300px; display: flex; justify-content: center; align-items: center; background: red;}.container img { position: absolute; z-index: -1; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;}
Việc sử dụng z-index: -1
đã làm cho img nằm hẳn dưới nền của container. Trong khi điều chúng ta muốn là chỉ nằm dưới các phần tử khác trong container mà thôi. Việc này nguyên nhân tại vì container dù sử dụng position relative nhưng không tạo ra một stacking context mới. Cách thông thường nhất để tạo một stacking context đó là sử dụng z-index kèm với position.
Nhưng chúng ta ở đây không muốn set z-index cho container bằng một số nào cả, giữ nguyên cấp độ mặc định của nó. Lúc này, sử dụng isolation là một giải pháp.
.container { position: relative; height: 300px; display: flex; justify-content: center; align-items: center; background: red; isolation: isolate;}.container img { position: absolute; z-index: -1; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;}
Thuộc tính này chắc là ít dùng, nhưng khi gặp một số giao diện thì nó sẽ khá hữu dụng.
Ví dụ chúng ta có giao diện dưới đây:
Để chữ nằm dọc vậy thì cách nhiều người nghĩ tới nhất có lẽ là dùng transform rotate
. Tuy nhiên, vì khi rotate từ chiều ngang sang chiều dọc thì diện tích nó chiếm vẫn là chiều ngang ban đầu, không chiếm không gian của chiều dọc, do đó nếu text dài hơn ảnh thì sẽ bị overflow.
Cách dễ thứ hai đó chính là dùng writing-mode
.
Xem qua docs của nó thì sẽ có 3 giá trị:
.wm { writing-mode: horizontal-tb; writing-mode: vertical-lr; writing-mode: vertical-rl;}
Chúng ta sẽ phân tích từng giá trị.
Đầu tiên là horizontal-tb
, đây là giá trị mặc định, nó sẽ hiển thị chữ theo chiều ngang, từ trái sang phải hay phải sang trái là tùy direction mình cài (mặc định là left to right).
Tiếp theo là vertical-lr
và vertical-rl
, lúc này chữ sẽ được viết theo chiều dọc.
2 ví dụ minh họa phía dưới lần lượt sử dụng vertical-lr và vertical-rl.
Nhìn có vẻ không khác gì, nhưng để thấy được sự khác nhau, chúng ta cần viết dài lên để nó rơi thành nhiều cột.
Và chúng ta sẽ thấy được sự khác biệt của left to right và right to left.
Đây là một loại display đặc biệt, khi mà nó sẽ làm cho container (nơi khai báo display: contents) sẽ coi như biến mất, chỉ còn các phần tử con bên trong được trải phẳng (flat) ra ngoài.
Vậy thuộc tính này có gì hữu dụng. Đó là đối với các trường hợp responsive, layout ở mobile với desktop khác nhau một cách rõ ràng.
Lấy ví dụ không mấy đẹp như dưới đây, ở desktop chúng ta sẽ có một layout như thế này:
Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?
Về mobile chúng ta có như này:
Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?
Nếu "may mắn" bạn sẽ gặp phải design như thế này. Bởi vì khu vực text ở desktop có background, nên html, css tối thiểu sẽ phải như thế này.
<div class="container"> <img src="..." /> <div class="content"> <h2>Title</h2> <p>Lorem....</p> </div></div>
.container { display: flex; /* ... */}.content { background: purple; /* ... */}
Vậy khi về mobile làm sao đưa h2
lên trên ảnh được, khi mà nó đang nằm trong content
? Lúc này chúng ta sẽ áp dụng được display: contents.
/* ... */@media (max-width: 768px) { .container { display: flex; flex-direction: column; /* ... */ } .content { background: purple; display: contents; /* ... */ } .content h2 { order: -1; }}
Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, ratione?
Thuộc tính này cũng khá hay ho. Khi mình sử dụng những generator để viết blog như này, thì rất nhiều style đã được định dạng sẵn. Ví dụ như table, nhiều lúc mình viết tutorial để hướng dẫn css với table, nhưng table hiện ra UI đã bị chỉnh sửa style, mình phải đè style lại cho từng thuộc tính rất mệt.
Lúc này, nhu cầu của mình là reset tất cả các thuộc tính về giá trị ban đầu của nó, lúc chưa có bất style nào.
Và thuộc tính all
sẽ giúp mình được chuyện đó.
table { all: unset;}
Ngoài ra, all
còn có những giá trị có thể khác nữa là: initial
, inherit
và revert
.
Chúng ta sẽ thảo luận chi tiết ý nghĩa các giá trị đó trong mục bên dưới.
Đây không phải thuộc tính, mà là giá trị mà có lẽ tất cả các thuộc tính css đều có, vậy chúng có nghĩa là gì?
initial
: Đây là một giá trị ám chỉ giá trị mặc định của một thuộc tính. Ví dụ, font-weight
sẽ có giá trị mặc định là normal
, tức là 400. Khi chúng ta sử dụng font-weight: initial
nó sẽ tương đương với font-weight: normal
.Bảng các giá trị mặc định của các thuộc tính được liệt kê ở đây: Link
inherit
: Dịch ra có nghĩa là kế thừa, tức là thuộc tính nào sử dụng giá trị này sẽ có kết quả là giá trị như các phần tử bọc bên ngoài nó. Trở lại thuộc tính font-weight
, là một thuộc tính có tính chất kế thừa, mặc định nó sẽ không mang giá trị initial
mà sẽ là inherit
, kế thừa giá trị từ các phần tử bọc bên ngoài nó.
Tất nhiên, nếu chúng ta muốn nó mang giá trị mặc định, chúng ta có thể set font-weight: initial
như ở trên.Tuy các thuộc tính thuộc loại kế thừa, giá trị nó thể hiện sẽ là inherit
, nhưng nếu là thẻ html
, tức là root, nó không thể kế thừa vì nó là phần tử ngoài cùng. Lúc này, các thuộc tính (thuộc loại inherit) dành cho html sẽ mang giá trị initial.
unset
: Khi sử dụng giá trị này, nó sẽ set lại giá trị của thuộc tính là inherit
nếu thuộc tính đó thuộc loại kế thừa, còn không sẽ là initial
. Tức là nó sẽ reset về initial hoặc inherit tùy loại thuộc tính.
.a { font-weight: unset; /*tương đương với*/ font-weight: inherit;}.b { display: unset; /*tương đương với*/ display: initial;}
revert
: Đây là một giá trị đặc biệt, tương tự như unset
. Tuy nhiên, thay vì chuyển thành initial hay inherit, nó sẽ chuyển về giá trị mặc định mà trình duyệt đã quy định cho thuộc tính đó.Ví dụ, nếu chúng ta reset giá trị display dành cho table sử dụng revert:
table { display: revert;}
display không phải thuộc tính dạng kế thừa, nên nếu dùng unset, chúng ta sẽ set nó về initial, cụ thể là inline. Nhưng vì dùng revert, nó sẽ reset về giá trị mà trình duyệt quy định cho nó:
table { display: revert;}/* Tương đương với */table { display: table;}
Ở dưới mình có một box màu xanh và một box màu vàng, box xanh bọc box vàng. Và 2 box hiện có content dài hơn chiều cao của box, nên bạn có thể sử dụng chuột để scroll trong box vàng hay box xanh.
Nếu bạn thử scroll trong box vàng, đến đáy của box vàng, nó sẽ tự động tiếp tục scroll box xanh.
Vậy, nếu chúng ta muốn scroll trong box vàng, đến đáy thì dừng lại, dù scroll tiếp (chuột đang ở trong box vàng) thì không làm cho box xanh scroll phải làm sao?
.yellow-box { overscroll-behavior: contain;}
Như vậy, chúng ta sẽ chặn được việc scroll tiếp tục dù chạm đáy box vàng.
overscroll-behavior còn có một giá trị nữa là none
. Nó tương tự như contain
, nhưng disable thêm hiệu ứng khác nữa.
Cụ thể, à mà bạn có thể tự đọc ở đây để có video minh họa: Link.