Học làm web (46) - CSS căn bản (22)

Tiếp theo của: Học làm web (45) - CSS căn bản (21)
----

Khối chứa

Như ở phần trên đã đề cập tới thuật ngữ khối chứa, vậy khối chứa (containing block) là gì? Theo đặc tả của CSS, khối chứa chính là một phần tử được sử dụng để chứa phần tử khác, điều quan trọng là phần tử chứa phải “đã được thiết lập một trong các kiểu định vị: relative, absolute hoặc fixed”.

Khối chứa có thể là “cha”, “ông” hoặc tổ tiên (ancestor) của phần tử được chứa. Nếu một phần tử không có “cha”, “ông” hoặc tổ tiên của nó là khối chứa, thì nó sẽ nhận phần tử html làm khối chứa mặc định.

Xem lại ví dụ ở trên, khi thiết lập kiểu định vị cho phần tử emabsolute, mặc dù p chứa em, tuy nhiên do p chưa được thiết lập kiểu định vị nào (relative, absolute, fixed), nên p không phải là khối chứa của em. Cuối cùng, em phải nhận html làm khối chứa của nó.

Để hiểu rõ hơn, cùng làm một thử nghiệm sau, chuyển phần tử p trở thành khối chứa của em. Cách làm rất đơn giản, chỉ việc thiết lập thuộc tính position cho p, với giá trị hay được dùng là relative. Lưu ý: không cần dịch chuyển phần tử p tới vị trí khác, cứ để nó ở vị trí cũ.

p {
  position: relative;
border: 1px solid red;
 }

Kết quả là phần tử p trở thành khối chứa, và em sẽ lấy phần tử p làm chuẩn, để dịch chuyển tới vị trí mới.

Xem hình kết quả,



Để ý, sau khi một phần tử được thiết lập kiểu định vị, việc dịch chuyển vị trí được căn theo cạnh phía trong đường viền (border) của khối chứa và cạnh ngoài (outer edge) của phần tử. Quan sát ví dụ sau, thêm width: 200px, và margin: 25px cho em.

[CSS]

em {
  width: 200px;
  margin: 25px;
  position: absolute;
  top: 30px;
  left: 60px;
  background-color: #ff6347;
 }

Xem hình minh họa,



Cũng giống như trong float, một phần tử inline khi được thiết lập kiểu định vị là absolute luôn được đối xử như một phần tử kiểu block. Như ở ví dụ trên, mặc dù phần tử em là kiểu inline, tuy nhiên, vẫn có thể thiết lập margin-top, margin-bottomwidth (lưu ý: một phần tử inline sẽ không thiết lập được margin-top, margin-bottomwidth) cho nó.

Khi một phần tử được thiết lập kiểu định vị, nó sẽ trở thành khối chứa, và tất cả các phần tử bên trong sẽ được thiết lập lại vị trí theo nó. Quan sát ví dụ dưới đây, khi div#content chưa được thiết lập kiểu định vị, phần tử li#special sẽ được căn theo toàn trang. Tuy nhiên, khi khi div#content được thiết lập position: relative thì li#special sẽ được căn theo div#content.

[HTML]

<div id="content">
    <p>Nhiệt độ trung bình tháng ở <em>Đà Lạt không bao giờ vượt quá 20°C</em>, ngay cả trong những tháng nóng nhất. Thành phố Đà Lạt là tỉnh lỵ của tỉnh Lâm Đồng, nằm trên cao nguyên Lâm Viên, thuộc vùng Tây Nguyên, Việt Nam. Từ xa xưa, vùng đất này vốn là địa bàn cư trú của những cư dân người Lạch, người Chil và người Srê thuộc dân tộc Cơ Ho. Cuối thế kỷ 19, khi tìm kiếm một địa điểm để xây dựng trạm nghỉ dưỡng dành cho người Pháp ở Đông Dương, Toàn quyền Paul Doumer đã quyết định chọn cao nguyên Lâm Viên theo đề nghị của bác sĩ Alexandre Yersin, người từng thám hiểm tới nơi đây vào năm 1893</p>
    <ul>
      <li>A</li>
      <li id="special">B</li>
      <li>C</li>
      <li>D</li>
    </ul>
  </div>

[CSS]

div#content {
    margin: 50px;
    /*position: relative;*/
    border: 1px solid red;
  }
  li#special {
    position: absolute;
    top: 20px;
    left: 20px;
  }

Xác định vị trí

Ở phần trên đã làm quen với việc dịch chuyển một phần tử sang trái và xuống dưới so với khối chứa. Phần này sẽ tìm hiểu thêm một số vấn đề liên quan đến việc xác định vị trí.

Nếu các giá trị của vị trí (top, right, bottom, left) là dương, phần tử sẽ được đẩy từ các cạnh về phía tâm của khối chứa. Nếu cạnh nào không được cung cấp giá trị, nó sẽ được thiết lập mặc định là auto và trình duyệt sẽ tự thêm các khoảng trắng để bố cục được hợp lý.

Quan sát ví dụ sau, với div#a là khối chứa; div#b là phần tử được định vị, thiết lập cả bốn giá trị để đặt div#b tại một ví trí xác định,

div#a {
position: relative; /* tạo khối chứa */
height: 120px;
width: 300px;
border: 1px solid;
background-color: #CCC;
}

div#b {
position: absolute;
top: 20px;
right: 30px;
bottom: 40px;
left: 50px;
border: 1px solid;
background-color: teal;
}

Xem hình minh họa,




Lưu ý: việc thiết lập bốn giá trị cho vị trí của div#b đã gián tiếp xác định chiều rộng và chiều cao của nó, cụ thể là rộng 220px và cao 60px. Như vậy, nếu vừa định vị (cả bốn giá trị) vừa thiết lập chiều rộng và chiều cao cho div#b thì rất có thể sẽ xảy ra tình trạng xung đột, khi mà kích thước của phần tử cộng với giá trị vị trí (do định vị) sẽ vượt quá kích thước của khối chứa.

CSS cũng có phần đặc tả để giải quyết tình trạng xung đột này, tuy nhiên khá phức tạp. Vì vậy, tốt nhất là nên tính toán cẩn thận để tránh tình trạng xung đột xảy ra, và chỉ nên xác định chiều rộng của phần tử, cùng với một hoặc hai giá trị về vị trí, còn lại nên để cho trình duyệt tự căn chỉnh.

Để xác định vị trí, ngoài đơn vị đo là px, cũng có thể sử dụng đơn vị là %. Ví dụ, đoạn mã đầu tiên dưới đây sẽ đặt hình ảnh ở vị trí sát cạnh trái và ở khoảng giữa theo chiều dọc; đoạn mã thứ hai sẽ đặt hình ảnh ở góc dưới bên phải của khối chứa.

img#A {
position: absolute;
top: 50%;
left: 0%; /* với giá trị 0 có thể không cần kí hiệu % */
}

img#B {
position: absolute;
bottom: 0%; /* với giá trị 0 có thể không cần kí hiệu % */
right: 0%; /* với giá trị 0 có thể không cần kí hiệu % */
}

Xem hình minh họa,



Lab2.5.d (exercise 15-4, p.365 [3])

Thuộc tính z-index

Như đã biết, sau khi thiết lập kiểu định vị, có thể đặt phần tử ở vị trí bất kì trong trang web. Điều này dẫn tới khả năng có nhiều phần tử chồng lấn lên nhau.

Mặc định, phần tử nào nằm trước trong mã nguồn sẽ nằm dưới, phần tử nào nằm sau trong mã nguồn sẽ nằm trên. Tuy nhiên, CSS cho phép thiết lập thứ tự xuất hiện của các phần tử khi chồng lấn bằng thuộc tính z-index.

Dưới đây là các đặc tính của z-index,

– Giá trị: number | auto | inherit

– Mặc định: auto

– Áp dụng: các phần tử đã thiết lập kiểu hiển thị là relative, absolute và fixed

– Kế thừa: không

Để dễ hiểu về z-index, hãy tưởng tượng giao diện trang web là một mặt phẳng, với hai trục tọa độ là Ox, và Oy để xác định chiều rộng và chiều cao tương ứng. Để xác định chiều sâu của một phần tử thì sẽ sử dụng thêm trục tọa độ Oz, trục này có chiều dương hướng từ sau màn hình ra trước màn hình. Như vậy, đối tượng nào có giá trị theo trục Oz càng lớn thì càng gần mắt người dùng và tất nhiên sẽ nằm trên, ngược lại giá trị nhỏ hơn hoặc âm thì sẽ nằm càng xa mắt người dùng (nên sẽ nằm dưới). Vậy, z-index chính là thứ tự theo trục Oz.

Ví dụ sau gồm ba phần tử chứa hình ảnh của ba chữ là A, B và C. Mặc định, sau khi thiết lập kiểu định vị và vị trí, thì chữ A sẽ nằm dưới cùng, đến chữ B, và chữ C nằm trên cùng. Tuy nhiên, với việc thiết lập giá trị z-index thì thứ tự hiển thị của các chữ bị đảo ngược.

[HTML]

<p id="A"><img src="A.gif" alt="A" /></p>
<p id="B"><img src="B.gif" alt="B" /></p>
<p id="C"><img src="C.gif" alt="C" /></p>

[CSS]

#A {
z-index: 10;
position: absolute;
top: 200px;
left: 200px;
}

#B {
z-index: 5;
position: absolute;
top: 225px;
left: 175px;
}

#C {
z-index: 1;
position: absolute;
top: 250px;
left: 225px;
}
Xem hình minh họa,



Kiểu định vị fixed

Ở các phần trên đã tìm hiểu hai kiểu định vị là relativeabsolute, phần này sẽ tìm hiểu kiểu định vị còn lại là fixed.

Cách làm việc của kiểu định vị fixed tương tự với kiểu định vị absolute, chỉ khác một điểm là nó luôn lấy màn hình (viewport) làm khối chứa, nghĩa là vị trí hiểu thị của phần tử sẽ lấy màn hình làm chuẩn.

Với kiểu định vị absolute, khi người dùng cuộn nội dung thì phần tử đã được định vị sẽ bị cuộn theo. Tuy nhiên, với kiểu định vị fixed thì phần tử vẫn nằm tại một vị trí cố định trên màn hình khi người dùng cuộn nội dung.

Kiểu định vị fixed thường được sử dụng để cố định thanh trình đơn (thanh điều hướng) tại một vị trí cố định trên màn hình của người dùng, nó không bị thay đổi vị trí khi người dùng cuộn phần nội dung.

Ví dụ, tại bài Lab2.5.d, sửa kiểu định vị của #award thành fixed và quan sát màn hình kết quả, hình ảnh giải thưởng sẽ luôn nằm tại một vị trí cố định khi người dùng cuộn nội dung xuống dưới.

#award {
  position: fixed;
  top: 35px;
  left: 25px;
}

2.5.4       Bài tập và câu hỏi ôn tập


1. Phát biểu nào sau đây không đúng về một phần tử được float?

a. Khi một phần tử được float, nó sẽ được đối xử giống như một phần tử kiểu block

b. Khi được thiết lập float, phạm vi “trôi dạt” của phần tử bao gồm cả vùng padding của phần tử chứa

c. Nội dung của phần tử inline sẽ bao quanh phần tử được float, trong khi khung chứa của phần tử inline thì không bị thay đổi

d. Phải cung cấp giá trị cho thuộc tính width khi float phần tử kiểu block

2. Luật CSS nào sau đây viết chưa đúng? Tại sao?

a. img { float: left; margin: 20px;}

b. img { float: right; width: 120px; height: 80px; }

c. img { float: right; right: 30px; }

d. img { float: left; margin-bottom: 2em; }

3. Để đảm bảo một divid là “footer” luôn nằm dưới một sidebar đã float, thì làm thế nào?

4. Chọn kiểu định vị phù hợp nhất (static, relative, absolute, fixed) cho mỗi tình huống sau,

a. Định vị một phần tử lấy khối chứa (containing block) nó làm chuẩn

b. Tách phần tử ra khỏi luồng hiển thị thông thường

c. Phần tử luôn được hiển thị theo màn hình (viewport)

d. Phần tử được hiển thị có thể chồng lấn lên các nội dung khác

e. Phần tử được hiển thị theo luồng thông thường, giống như thứ tự trong mã nguồn

f. Sau khi được thiết lập kiểu định vị, phần không gian ban đầu của phần tử vẫn được duy trì, mặc dù nó đã được hiển thị ở vị trí mới

g. Sau khi được thiết lập kiểu định vị, phần không gian ban đầu của phần tử sẽ bị thu hồi, khi nó đã được hiển thị ở vị trí mới

h. Người thiết kế có thể thay đổi thứ tự xuất hiện với thuộc tính z-index

i. Vị trí mới của phần tử được tính dựa trên vị trí gốc (vị trí khi nó hiển thị ở chế độ thông thường)

-----------
Cập nhật [18/7/2018]
-----------
Xem thêm: Tổng hợp các bài viết về Học làm web
Xem thêm: Học làm web (47) - CSS căn bản (23)