Xây Dựng Layout Đơn Giản Với CSS Grid

Xây Dựng Layout Đơn Giản Với CSS Grid

Giới Thiệu Chung

Hôm nay mình sẽ hướng dẫn tất cả mọi người xây dựng một trang lading page với grid css.
Thì mình sẽ convert UI trang home của blog thanhlongdev với grid css bao gồm giao diện desktop và mobile.

Mục Đích Bài Viết

Đây không phải là chủ đề gì quá xa lạ và mới mẻ với các anh em front end dev.
Nhưng mình vẫn muốn chia sẻ để giúp các bạn beginner nắm kĩ hơn các kiến thức về cách dựng một layout và chia component ra làm sao cho nó hợp lý, mà không cần sử dụng bất kì framework nào cả thông qua việc xây dựng một project thực tế.
Mình chỉ mong muốn là các bạn đọc bài của mình thật kĩ và rõ ràng.

Bắt Đầu Thôi Nào

Lên Ý Tưởng

Ý tưởng để mà convert UI trang home của thanhlongdev cũng đơn giản thôi. Mình sẽ chia làm 3 phần nha header, main và footer để code nha.
Chúng ta sẽ code từ giao diện desktop đến mobile. Trong đó, phần main của giao diện desktop ta sẽ chia các topic theo từng cột mà template đã định nghĩa sẵn, còn mobile thì ta sẽ các bài topic đều một cột cả.

Cấu Trúc Thư Mục Cho Dự Án

Cấu trúc thư mục cho project này cũng đơn giản thôi chả có gì phức tạp cả hihihi
Ví dụ: Mình sẽ tạo một folder project với tên là Layout With Grid. Trong folder đó các bạn tạo cho mình một file index.html và 1 folder css để chứa 2 file đó là style.css, reponsive.css

Bắt Đầu Code Thôi

Phần Header

Trong phần header này chúng ta sẽ sử dụng css grid để chia layout và rõ hơn nữa đó là thuộc tính grid-template-columns để có thể chia layout cho nó.
grid-template-columns sẽ tương ứng với số cột, các giá trị sẽ tương ứng với chiều rộng của các cột lần lượt từ trái sang phải.
Còn grid-template-rows sẽ tương ứng số hàng, các giá trị sẽ tương ứng với chiều cao của các hàng lần lượt từ trên xuống dưới.
Chúng ta sẽ phân tích và chia tách từng component một để việc code dễ dàng hơn nha

Như các bạn thấy ở trên thì fr được viết tắt của "fraction" (phân số) là gì??
Thì nó cũng là một đơn vị kích thước tương tự như px, rem, em nhưng nó được thiết kế dành riêng cho grid. 1fr tương ứng với một phần trong không gian trống của grid container.
Code HTML

Lý do tại sao mình không copy code vào đây cho các bạn dễ dàng code hơn, bởi vì mình mong muốn các bạn nhìn vào đấy rồi làm theo tránh trường hợp copy,... Mục đích chỉ muốn tốt cho các bạn thôi hihihi.
Và đây là header khi mình code xong phần html cho nó. Nhìn củ chuối lắm các ông ạ =)))

Code CSS
Trong phần CSS này mình sẽ sử dụng grid để chia layout cho navbar và banner. Chúng ta sẽ đi từng phần nha trước tiên là navbar rồi tiếp đến là banner.

Repeat được sử dụng khi grid có nhiều hàng và cột giống nhau thì chúng ta nên sử dụng để khai báo nhanh hơn.
Justify-items sẽ căn chỉnh nội dung theo trục hoành (trục x), còn align-items sẽ căn chỉnh nội dung bên trong grid theo trục tung (trục y).

* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    font-family: 'Open Sans', sans-serif;
}

li { list-style: none; }

a { text-decoration: none; }

/* header */
header {
    background: #0a0b0c;
    padding: 0 5vw;
    color: #fff;
}

/* Navbar */
nav {
    margin: 0 auto; // Có chức năng căn giữa khi sử dụng chung với width
    max-width: 1040px; // Set width khi vượt quá 1040 thì sẽ bay vào giữa
    width: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.menu {
    padding-top: .5rem;
    display: grid;
    grid-template-columns: repeat(4, .2fr);
    justify-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
}

/* Nav right */
.site-nav-right {
    display: grid;
    grid-template-columns: 12fr 1fr;
    padding: 10px 0;
    height: 64px;
    justify-items: right;
}

/* Banner */
.banner-header {
    display: grid;
    justify-items: center;
    align-items: center;
    padding: 6vw 3vw;
    min-height: 200px;
    max-height: 340px;
}

.banner-header .site-description {
    text-align: center;
    font-weight: 500;
    padding: 5px 0;
    font-size: 1.2rem;
    line-height: 1.4em;
    opacity: .8;
}

Style css các chi tiết trong phần header mà các bạn có thể tự css theo sức sáng tạo của mình nha.

Và đây là kết quả khi chúng ta đã hoàn thành xong phần header <3

Phần Main

Trong phần này mình sẽ chia layout giống như ý tưởng mà mình đã nói ở trên. Mình sẽ bao bọc ở ngoài một class="posts" bên trong đó là những class dùng để chia bố cục từng phần một và ngăn cách nhau bằng thẻ <hr>, bên trong là thẻ article dùng để chứa các bài topic các bạn xem ảnh ở dưới để có thể rõ hơn nha.

Code HTML
Dưới đây là tổng quát những class chính trong phần main.

Còn dưới đây là những class chi tiết trong thẻ article bao gồm: ảnh bìa, tiêu đề, mô tả, tác giả, thẻ tag,... Và có một lưu ý nữa đó là những bài topic đều có thể được click vào để xem chi tiết nên cần đặt trong thẻ liên kết a.

     <article class="post-wrapper">
                    <a href="#">
                        <img class="img-post"
                            src="https://digitalpress.fra1.cdn.digitaloceanspaces.com/4tg23ij/2020/09/33.png " alt="">
                    </a>
                    <div class="content-post">
                        <a href="#">
                            <div class="tag-post">Lập Trình Web</div>
                            <h2 class="title-post">Hướng Dẫn Xây Dựng Books Store Với NodeJS, Express và MongoDB - Phần 4 </h2>
                            <p class="desc-post">
                                Chức Năng Hiển Thị Chi Tiết, Cập Nhật Và Xóa Books Định Nghĩa Và Controller Router Hiển
                                Thị Chi Tiết Trong Books Mình sẽ nói sơ qua một chút về
                            </p>
                        </a>
                        <div class="author-post">
                            <a href="#">
                                <img class="avatar-author"
                                    src="https://digitalpress.fra1.cdn.digitaloceanspaces.com/4tg23ij/2020/05/IMG_20200331_120727-1.jpg"
                                    alt="" />
                            </a>
                            <div class="content-author">
                                <div>
                                    <a href="">Đặng Thanh Long</a>
                                </div>
                                <span class="post-card-byline-date"><time datetime="2020-09-12">12 Th09 2020</time>
                                    <span class="bull">•</span> 13 min read</span>
                            </div>
                        </div>
                    </div>
                </article>

Code CSS
Những class "posts-columns-1", posts-columns-3 và posts-columns-2 thì sẽ tương ứng lần lượt với các cột như sau grid-template-columns: 1fr; grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(2, 1fr).
Grid-column-gap là khoảng cách giữa các cột và ngược lại grid-row-gap sẽ là khoảng cách giữa các hàng với nhau.

/* Main */
main {
    padding: 0 5vw;
}

.margin-main {
    margin: 2.5rem 0 6rem;
}

.posts {
    max-width: 1040px;
    width: 100%;
    margin: 0 auto;
}

.posts-columns-1 {
    display: grid;
    grid-template-columns: 1fr;
}

.posts-columns-3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-column-gap: 2rem;
}

.posts-columns-2 {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-column-gap: 2rem;
}

Style css các thành phần chi tiết trong thẻ article, có một vấn đề nhỏ đó là ảnh bìa và nội dung trong thẻ class="post-wrapper" được bao bọc bởi class="posts-columns-1" phải nằm ngang hàng với nhau vậy bây giờ ta phải làm sao nhờ. Thì đơn giản thôi trong class="post-wrapper" chúng ta sẽ sử dụng grid và thuộc tính grid-template-columns để làm điều đó hihihi.

Và đây là kết quả khi chúng ta đã hoàn thành xong phần main nhìn cũng ra gì phết nhờ =)))

Phần Footer

Phần này thì khá là đơn giản không có gì phức tạp cả nên mình sẽ đi nhanh phần này nha. Trước tiên các bạn tạo cho mình một thẻ footer bên trong sẽ chứa hai thẻ div tương ứng với hai nội dung trong footer, bây giờ ta chỉ cần sử dụng grid và một số thuộc tính của nó là có thể cân được footer rồi hihi.
Code HTML

 <!-- Footer -->
    <footer class="site-footer">
        <div class="site-footer-content posts">
            <section class="copyright">
               <a href="https://www.thanhlongdev.com">Thanh Long Dev</a> © 2020
            </section>
            <div class="site-footer-nav">
                <a href="https://www.thanhlongdev.com">Latest Posts</a>
                <a href="https://www.facebook.com/thanhlongdev/" target="_blank" rel="noopener">Facebook</a>
            </div>
        </div>
    </footer>

Code CSS
Phần css này chắc mình hổng cần giải thích gì nhờ các bạn nhìn vào chắc cũng hiểu được mình đang làm gì rồi.

Đây là kết quả khi chúng ta đã hoàn thành xong phần footer:

Và đây là giao diện desktop khi chúng ta đã dựng xong layout <3 <3 <3

Reponsive Layout Grid

Ảnh ở trên là giao diện mobile & tablet khi mình chưa reponsive nha, nhìn kinh vl kkkkk
Các bạn tạo cho mình file reponsive nhớ là phải import vào file index.html nha. Nếu mà muốn reponsive thì các bạn sử dụng thuộc tính media query nha.
Ở đây mình có soạn sẵn các media phù hợp với từng loại kích thước với nhau rồi nha, các bạn chỉ cần copy paste rồi sau đó code thôi nha.

@media(min-width: 1366px){
// code here
}
@media(min-width:1200px) and (max-width:1365px){
// code here
}
@media(min-width:992px) and (max-width:1199px){
 // code here
}
@media(min-width:768px) and (max-width:992px){
  // code here
}
/* --------Tablet-------- */
@media (min-width:480px) and (max-width:768px){
 // code here
}
/* ---------Mobile-------- */
@media only screen and (min-width:240px) and (max-width:480px){
// code here
}

Reponsive Giao Diện Mobile

Bây giờ chúng sẽ reponsive từ trên xuống dưới từ ngoài vào trong, từ trong ra ngoài từ header đến footer =))))

  • Thứ nhất trong phần heder bạn ẩn cho mình thằng nav-right.
  • Thứ hai trong phần main mình muốn các bài topic chỉ hiển thị một cột duy nhất.
  • Thứ ba phần footer mình sẽ canh chỉnh cho nó ở giữa.

Reponsive Giao Diện Tablet

Trong phần này thì cũng khá đơn giản, chúng ta chỉ cần reponsive phần main là xong rồi.

  • Phần main của tablet này mình muốn các bài topic chỉ hiển thị một cột duy nhất giống như phần main trong mobile vậy.

    Và đây là giao diện Mobile & Tablet mà mình đã reponsive nha:

    Ôi Vui Quá Cuối Cùng Cũng Xong Rồi hihihi
    Các bạn tham khảo trang homepage thanhlongdev mà mình đã deploy lên firebase tại đây nha

Lời Kết

Vậy là xong bài Xây Dựng Layout Đơn Giản Với CSS Grid. Mình mong muốn sau khi các bạn hoàn thành xong project này sẽ hiểu và nắm rõ hơn về grid, flex và cách phân tích từng component. Các bạn có thể dựa vào project này để có thể phát triển và scale project này lớn hơn nữa nha.
Các bạn nhớ like và theo dõi fanpage Thanh Long Dev để nhận những thông báo về bài viết mới nhất nha.
Nếu các bạn cảm thấy bài viết của mình hay thì các bạn có thể ủng hộ mình để mình có thêm động lực để ra những bài topic hay và chất lượng hơn ủng hộ mình tại đây nha.
Chúc Các Bạn Thành Công!!