[CSS] Snake layout – Làm thế nào để tạo layout dạng con rắn

2 min read

Snake layout là gì?

Snake layout (hay còn gọi là chain layout) là layout mà các block của 1 hàng khi đạt đến số lượng giới hạn nào đó nó sẽ bị wrap xuống nhưng đặc biệt là block của hàng tiếp theo phải ở ngay dưới block của hàng trước đó. Nên các block sẽ uốn lượn như 1 con rắn như cái hình to đùng ở trên.

Xử lý bằng Flex box

Mình nghĩ cách đơn giản nhất là bọc mỗi hàng vào 1 container, hàng lẻ sẽ được sắp xếp theo thứ tự từ trái qua phải như bình thường, hàng chẵn sẽ được sắp xếp theo thứ tự ngược lại.

Vậy ở đây chúng ta sẽ sử dụng flex box cho mỗi container. Chúng ta sẽ select các container ở vị trí chẵn và đảo ngược thứ tự của những element con.

<div class="snakeContainer">
  <div>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
  <div>
    <span>5</span>
    <span>6</span>
    <span>7</span>
    <span>8</span>
  </div>
  <div>
    <span>9</span>
    <span>10</span>
    <span>11</span>
    <span>12</span>
  </div>
</div>

<style>
.snakeContainer div:nth-child(even){
  display: flex;
  flex-direction: row-reverse; /*đảo chiều*/
  justify-content: flex-end;
}

.snakeContainer div:nth-child(odd){
  display: flex;
}
</style>

Xử lý bằng Grid box

Hmm, có vẻ dùng flex cũng đơn giản nhưng mà cứ mỗi hàng mình phải bọc trong 1 container. Có cách nào mà không cần bọc từng hàng mà vẫn xử lý được trường hợp này không nhỉ?

Câu trả lời là có, mình sẽ sử dụng grid.

  • Đầu tiên, mình xác định 1 hàng có bao nhiêu element. Ví dụ 1 hàng có 4 element.
  • Vậy cứ mỗi 4 element thì mình sẽ đảo chiều 4 element tiếp theo.
  • Chúng ta sẽ sử dụng property grid-column để sắp xếp lại thứ tự của element.
  • Cho n >= 0, Element ở vị trí (8n+5) (element đầu tiên của hàng chẵn) sẽ được đặt ở vị trí cuối cùng từ trái qua phải (grid-column: 4), Element tiếp theo ở vị trí (8n+6) sẽ được đặt ở vị trí áp cuối (grid-column: 4). Cứ như vậy cho đến element (8n+8) (element cuối cùng của hàng chẵn) sẽ ở vị trí đầu tiên (grid-column: 1).

*note: property grid-column sẽ tạo 1 hàng mới cho element đó nên phải dùng grid-auto-flow: dense; để tự động lấp lại những khoảng trống nếu không thì sẽ như hình dưới

<div class="snakeContainer">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
    <span>6</span>
    <span>7</span>
    <span>8</span>
    <span>9</span>
    <span>10</span>
    <span>11</span>
    <span>12</span>
</div>

<style>
.snakeContainer {
  display:grid;
  grid-auto-flow: dense; /*Lấp lại những ví trí trống*/
}

.snakeContainer > span:nth-child(8n + 5) { grid-column:4; }
.snakeContainer > span:nth-child(8n + 6) { grid-column:3; }
.snakeContainer > span:nth-child(8n + 7) { grid-column:2; }
.snakeContainer > span:nth-child(8n + 8) { grid-column:1; }
</style>

Ref:

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *