Alternatif Mixin Sederhana untuk Grid CSS Standar
Indonesian (Bahasa Indonesia) translation by Andy Nur (you can also view the original English article)
Selama beberapa tahun terakhir sistem grid CSS telah menjadi cara yang sangat populer untuk memproduksi scaffolding tata letak dalam desain web dengan cepat.
Mereka bisa menjadi sumber daya hemat waktu yang fantastis, dengan coder berbakat yang memiliki sistem yang dibuat secara cerdas yang memenuhi beragam kemungkinan tata letak yang mungkin perlu dibuat oleh desainer. Namun, ini bukan satu-satunya cara untuk mendekati tata letak web berbasis grid, dan hari ini kita akan mengecek alternatifnya.
Bagaimana Sistem CSS Grid Bekerja
Sistem grid biasanya terdiri dari sejumlah kolom, (biasanya dua belas atau enam belas), dan kemampuan untuk mengatur elemen, (biasanya div dengan class yang diterapkan), hingga lebar X kolom tersebut.
Misalnya, area konten dapat diatur ke sembilan dari dua belas kolom, sedangkan bilah samping di sebelahnya diatur ke tiga atau dua belas kolom. Tata letak sering juga mencakup wadah luar dengan lebar yang tetap, wadah baris di dalamnya yang membungkus kolom, dan mengatu lebar saluran di antara kolom.
Mari kita cepat melihat bagaimana tata letak situs web "header, content, sidebar, footer" klasik dapat dibangun menggunakan teknik yang umum untuk CSS grid:



Menggunakan sistem grid CSS untuk membuat tata letak seperti ini bisa sangat cepat dan mudah. Namun, sementara ada banyak nilai yang ditawarkan, ada juga beberapa kelemahan untuk menggunakan sistem seperti ini. Kerugian ini tidak berarti bahwa sistem grid CSS itu "buruk", hanya saja seperti halnya tool apa pun yang kamu harus membiasakan diri dengan pro dan kontra untuk menentukan apakah itu cocok untuk proyek spesifimu.
Kerugian untuk CSS Grid
Meskipun semua sistem grid CSS berbeda, kelemahan terbesar yang biasanya ada di antaranya adalah:
- Jumlah kode tidak terpakai yang berpotensi tinggi
Library penuh pada class grid cenderung berada di mana saja dari 200 hingga 700 baris kode (tidak diminifikasi), namun dalam desain yang relatif sederhana, sebagian besar kode itu mungkin tidak pernah dapat digunakan. - Pembatasan tata letak
Karena grid dihitung sebelumnya, mereka cenderung menetapkan lebar yang sulit diubah, semisal. untuk wadah, lebar kolom, lebar selokan. Desainnya kemudian menjadi terbatas untuk bekerja dengan lebar tersebut. - Memperbaiki piksel daripada tata letak berbasis em / rem atau persen
Lebar grid dan/atau media query sering didasarkan pada nilai piksel, mencegah penggunaan em / rem yang lebih fleksibel dan terukur atau nilai persen untuk desain.
Catatan: Untuk informasi tentang kelebihan desain berbasis em / rem vs px, silakan baca Taking the “Erm..” Out of Ems - Menetapkan jumlah kolom secara keseluruhan
Grid yang dihitung sebelumnya cenderung menggunakan dua belas atau enam belas kolom, artinya jika kamu menginginkan jumlah kolom keseluruhan yang berbeda, kamu kurang beruntung. - Markup non semantik
Penggunaan, class-class grid yang telah dihitung sebelumnya mengharuskan penempatan banyak nama class non-semantik di seluruh dokumen, seperti "row", "col" dan sebagainya. - Batasan untuk bersarang
Seringkali sistem grid hanya dapat memiliki kolom bersarang di dalam satu atau dua kali, membatasi kompleksitas dan fleksibilitas generasi tata letak.
Ketika sampai pada itu, alasan sebenarnya desainer menggunakan sistem grid CSS adalah untuk membuat generasi tata letak lebih cepat dan lebih mudah. Jadi pertanyaannya adalah:
Dapatkah pembuatan tata letak dilakukan dengan cepat dan mudah sekaligus mengatasi keterbatasan yang tercantum di atas?
Berkat kedatangan preprosesor CSS seperti LESS dan SASS / SCSS yang dapat bekerja dengan variabel, melakukan perhitungan dan menghasilkan CSS sesuai kebutuhan melalui mixin, untuk banyak kasus penggunaan jawabannya adalah:
Ya itu benar-benar bisa!
Alternatif, Solusi yang Diproses Sebelumnya
Kunci dari solusi alternatif yang akan kita bahas adalah "mixins", tersedia dalam LESS dan SASS / SCSS. Singkatnya, mixin adalah paket aturan yang dapat digunakan kembali yang dapat menampilkan CSS berbeda tergantung pada informasi apa yang diteruskan kepada mereka untuk diproses.
Mulai dari sini, kita akan menganggap kamu memiliki pemahaman penting tentang apa itu preprosesor dan bagaimana mereka bekerja dengan mixin dan variabel, jadi jika kamu baru mengenal konsep-konsep ini, saya sarankan memulai dengan membaca informasi yang disediakan di http://lesscss.org/
Sebelum kita mulai, saya juga akan menunjukkan bahwa sudah ada beberapa library pada LESS dan SASS mixin yang bekerja untuk mengatasi keterbatasan grid CSS yang telah dihitung, seperti:
Namun, kita akan mengambil pendekatan yang berbeda pada library ini dengan berbagai cara. Sekali lagi, tidak ada cara yang benar atau salah untuk mendekati hal-hal tsb, itu hanya masalah memahami pro dan kontra ketika memutuskan pendekatan apa yang akan digunakan untuk proyemu.
Catatan: Saya akan menulis mixin ini dalam LESS, karena bisa sedikit lebih sulit untuk membuat LESS melakukan operasi yang canggih daripada SASS, sehingga akan lebih mudah bagi pengguna SASS untuk mengadaptasi mixin LESS daripada sebaliknya.
Kamu dapat menggunakan metode yang kamu inginkan sendiri untuk mengkompilasi file preprocesso-mu, namun saya akan menyertakan paket "LESScompiler" dasar yang berjalan pada Node.js/NPM dan Grunt yang dapat kamu gunakan. Instruksi termasuk dalam file readme.md.
Menangani Tata Letak Klasik
Kita melihat di atas bagaimana tata letak "'header, konten, sidebar, footer" yang ada di mana-mana dapat dibuat menggunakan seperangkat class-class grid CSS, menyadap sekitar 200 hingga 700 baris kode. Sekarang mari kita lihat bagaimana kita dapat membuat tata letak yang sama ini melalui mixins LESS, menjaga jumlah CSS yang diperlukan untuk minimum absolut, tidak menggunakan nilai pixel, dan mempertahankan markup semantik.
Pertama, mari kita lihat HTML kita:
1 |
|
2 |
<!DOCTYPE html>
|
3 |
<html lang="en"> |
4 |
<head>
|
5 |
<meta charset="UTF-8"> |
6 |
<title>Classic Layout</title> |
7 |
<script type='text/javascript' src='js/modernizr.js'></script> |
8 |
<link rel="stylesheet" href="css/normalize.css"> |
9 |
<link rel="stylesheet" href="css/classiclayout.css"> |
10 |
</head>
|
11 |
<body>
|
12 |
<header>
|
13 |
|
14 |
</header>
|
15 |
<main>
|
16 |
<article>
|
17 |
|
18 |
</article>
|
19 |
<aside>
|
20 |
|
21 |
</aside>
|
22 |
</main>
|
23 |
<footer>
|
24 |
|
25 |
</footer>
|
26 |
</body>
|
27 |
</html>
|
Perhatikan bahwa tidak ada satu class pun yang digunakan pada tahap ini, hanya tag HTML5 semantik murni. Untuk HTML ini kita akan menerapkan kode LESS berikut, menggunakan mixin dan variabel yang akan dijelaskan segera:
1 |
|
2 |
header, main, footer { |
3 |
.Row;
|
4 |
background-color: #ccc; |
5 |
min-height: 200 * @toRems; |
6 |
}
|
7 |
|
8 |
article { |
9 |
.Cols( 3 ); |
10 |
min-height: 500 * @toRems; |
11 |
background-color: #ddd; |
12 |
}
|
13 |
|
14 |
aside { |
15 |
.Cols( 1 ); |
16 |
min-height: 500 * @toRems; |
17 |
background-color: #eee; |
18 |
}
|
... yang akan menghasilkan 35 baris CSS berikut:
1 |
|
2 |
header, |
3 |
main, |
4 |
footer { |
5 |
max-width: 75rem; |
6 |
width: 100%; |
7 |
margin: 0 auto; |
8 |
background-color: #ccc; |
9 |
min-height: 12.5rem; |
10 |
}
|
11 |
header:before, |
12 |
main:before, |
13 |
footer:before, |
14 |
header:after, |
15 |
main:after, |
16 |
footer:after { |
17 |
content: ""; |
18 |
display: table; |
19 |
}
|
20 |
header:after, |
21 |
main:after, |
22 |
footer:after { |
23 |
clear: both; |
24 |
}
|
25 |
article { |
26 |
width: 75%; |
27 |
float: left; |
28 |
min-height: 31.25rem; |
29 |
background-color: #ddd; |
30 |
}
|
31 |
aside { |
32 |
width: 25%; |
33 |
float: left; |
34 |
min-height: 31.25rem; |
35 |
background-color: #eee; |
36 |
}
|
... dan hasilnya akan kita lihat di browser, pada resolusi layar 1920 x 1080, adalah:



Perhatikan bahwa karena kita tidak bekerja dengan pengaturan lebar piksel yang tetap, tata letak ini sudah memiliki respons dasar dari kata yang dituju. Layout yang sama terlihat seperti ini pada lebar 1024px:



Dan seperti ini pada lebar 768px:



Kita akan membahas responsif pada ukuran yang lebih kecil nanti, tetapi pertama-tama mari kita periksa mixin LESS dan variabel yang digunakan untuk membuat tata letak di atas.
1 |
|
2 |
//
|
3 |
// Variables for em / rem use |
4 |
//
|
5 |
|
6 |
@base_px: 16; //set to the most common base px size used in browsers, should generally be left at default |
7 |
|
8 |
@toRems: (1 / @base_px) + 0rem; //allows you to set values as the default px size to target, which is then converted into scalable rem values. |
9 |
|
10 |
@toEms: (1 / @base_px) + 0em; //same as above, but with em values |
11 |
|
12 |
//
|
13 |
// Grid mixins |
14 |
//
|
15 |
|
16 |
@default-width: 1200 * @toRems; |
17 |
|
18 |
@default-colspan: 1; |
19 |
|
20 |
@default-total_cols: 4; |
21 |
|
22 |
.Row ( @width : @default-width ) { |
23 |
max-width: @width; |
24 |
width: 100%; |
25 |
margin: 0 auto; |
26 |
// clear at the end of container |
27 |
&:before,
|
28 |
&:after { |
29 |
content:""; |
30 |
display:table; |
31 |
}
|
32 |
&:after { |
33 |
clear:both; |
34 |
}
|
35 |
}
|
36 |
|
37 |
.Cols ( @colspan : @default-colspan; @total_cols : @default-total_cols ) { |
38 |
width: ( @colspan * (100 / @total_cols) ) + 0%; |
39 |
float: left; |
40 |
}
|
Mari kita melangkahi setiap elemen dari apa yang terjadi di atas.
Konversi px ke em / rem yang mudah
1 |
|
2 |
//
|
3 |
// Variables for em / rem use |
4 |
//
|
5 |
|
6 |
@base_px: 16; //set to the most common base px size used in browsers, should generally be left at default |
7 |
|
8 |
@toRems: (1 / @base_px) + 0rem; //allows you to set values as the default px size to target, which is then converted into scalable rem values. |
9 |
|
10 |
@toEms: (1 / @base_px) + 0em; //same as above, but with em values |
Variabel di bagian atas kode membuat kita untuk mengatur dengan mudah menghasilkan nilai em atau rem yang dapat diukur di seluruh stylesheet daripada nilai px. Namun, menggunakan variabel-variabel ini juga akan memungkinkan kita untuk membuat konsep desain kita dalam piksel untuk memulainya, karena itu adalah latihan mental yang lebih mudah untuk membayangkan seperti apa ruang 500px daripada 31,25rem.
Sebagai contoh, dalam desain dasar kita, kita tidak ingin elemen header, main atau footer lebih lebar dari 1200 piksel pada setiap saat. Tetapi daripada menetapkan 1200px
sebagai max-width
, kita mengonversi nilai 1200 itu ke rem dengan mengalikannya melaui variabel @toRems
seperti:
1 |
|
2 |
1200 * @toRems; |
Ini akan menghasilkan nilai 75rem
, yang berarti bahwa jika browser atau pengguna telah menetapkan ukuran font default untuk sesuatu selain dari standar umum 16px, seluruh tata letak situs akan berskala secara proporsional.
Hal yang sama juga dapat dilakukan untuk menghasilkan nilai em
, dengan menggunakan variabel @toEms
.
Mixin .Row()
1 |
|
2 |
@default-width: 1200 * @toRems; |
3 |
|
4 |
.Row ( @width : @default-width ) { |
5 |
max-width: @width; |
6 |
width: 100%; |
7 |
margin: 0 auto; |
8 |
// clear at the end of container |
9 |
&:before,
|
10 |
&:after { |
11 |
content:""; |
12 |
display:table; |
13 |
}
|
14 |
&:after { |
15 |
clear:both; |
16 |
}
|
17 |
}
|
Mixin pertama yang digunakan adalah mixin .Row()
.
Daripada menggunakan class ".container", kita memanggil mixin ini di mana pun kita ingin elemen dipusatkan dengan lebar maksimum. Dalam kasus tata letak klasik kita, kita menyebutnya mixin pada elemen header
, main
dan footer
.
Mixin menetapkan mix-width
bersama dengan width
100%. Ini memberi kita responsif dasar dengan membuat elemen secara otomatis menyesuaikan untuk mengisi ruang yang tersedia setiap kali viewport lebih kecil dari nilai max-width
.
Ini juga mengatur margin
ke 0 auto
sehingga elemen akan secara otomatis ke tengah.
Akhirnya, ini menambahkan elemen pseudo :before
dan :after
dan menggunakannya untuk menghapus secara otomatis di akhir elemen. Ini diperlukan agar ketika kita mulai menambahkan kolom di dalam elemen pengaturan float-nya akan dihapus.
Mixin menerima satu parameter, suatu nilai @width
:
1 |
|
2 |
.Row (@width : @default-width ) { |
Nilai ini kemudian diteruskan ke properti max-width
:
1 |
|
2 |
max-width: @width; |
Saat mixin memiliki parameter lebar yang diteruskan, semisal. .Row( 40rem )
, nilai itu akan diterapkan ke properti max-width
.
Namun, jika mixin dipanggil tanpa melewati parameter, semisal. .Row
, nilai default akan digunakan sebagai gantinya. Nilai default itu disimpan pada variabel @default-width
, yang ditetapkan di tempat yang kamu melihat:
1 |
|
2 |
@default-width: 1200 * @toRems; |
Seperti yang akan kamu pahami dari apa yang kita bahas di atas tentang variabel @toRems
, ini berarti lebar maksimum default dari setiap elemen yang digunakan mixin ini adalah 1200 piksel, yang dikonversi menjadi nilai rem.
Dengan menggunakan mixin ini, kamu sekarang dapat mengatur elemen apa saja untuk di tengahkan pada lebar max-width
-mu, atau pada max-width
lainnya yang ingin kamu terapkan. Ini berarti kamu dapat mengubah lebar seluruh situs hanya dengan mengubah nilai variabel @default-width
. Sebagai contoh:
1 |
|
2 |
@default-width: 800 * @toRems; |
...mengubah tata letak dasar menjadi:



Atau kamu dapat mengubah lebar elemen tunggal sekaligus, dengan melewatkan parameter width melalui mixin.
Sebagai contoh, menerapkan mixin seperti ini:
1 |
|
2 |
header, footer { |
3 |
.Row;
|
4 |
background-color: #ccc; |
5 |
min-height: 200 * @toRems; |
6 |
}
|
7 |
|
8 |
main { |
9 |
.Row( 800 * @toRems ); |
10 |
background-color: #ccc; |
11 |
}
|
... akan memberimu:



Mixin .Cols()
1 |
|
2 |
@default-colspan: 1; |
3 |
|
4 |
@default-total_cols: 4; |
5 |
|
6 |
.Cols ( @colspan : @default-colspan; @total_cols : @default-total_cols ) { |
7 |
width: ( @colspan * (100 / @total_cols) ) + 0%; |
8 |
float: left; |
9 |
}
|
Karena kita tidak menggunakan lebar piksel yang tetap, dan kita ingin tata letak kita tetap sepenuhnya fleksibel, semua lebar kolom kita akan berdasarkan persentase. Kita menggunakan mixin .Cols()
untuk menghitung persentase ini.
Berdasarkan nilai yang kamu masukkan ke dalam mixin, rumus sederhana digunakan untuk menentukan nilai lebar persen yang harus diterapkan pada elemen. Nilai float
elemen juga diatur ke left
sehingga kolom akan duduk berdampingan (kamu akan ingat kita secara otomatis menghapus float yang diterapkan ke kolom melalui mixin .Row()
).
Dengan mixin .Cols()
kamu bisa menentukan berapa banyak kolom lebar yang kamu inginkan untuk elememu, seperti halnya dengan sistem grid CSS biasa. Ini dilakukan dengan meneruskan parameter @colspan
melalui mixin, atau dengan mengatur default untuk mixin melalui variabel @default-colspan
.
Namun, tidak seperti kebanyakan sistem grid CSS, kamu juga memiliki kontrol penuh atas jumlah kolom total yang nilainya relatif terhadap itu, daripada terjebak dengan total kolom 12 atau 16. Kolom total dapat ditetapkan dengan meneruskan parameter @total_cols
melalui mixin, atau dengan mengatur default mixin melalui variabel @default-total_cols
.
Dalam contoh kita sebelumnya tentang bagaimana tata letak "klasik" kita akan dibangun menggunakan grid CSS yang khas, area konten ditetapkan ke 9 dari 12 kolom, (yaitu tiga perempat), sedangkan bilah sisi adalah 3 dari 12 kolom, (yaitu seperempat). Namun, untuk tujuan sederhana dari tata letak ini, kita benar-benar tidak memerlukan kedua belas kolom.
Yang kita coba lakukan adalah mengatur area konten kita menjadi lebar 3/4, dan sidebar menjadi 1/4 dari lebar. Jadi memecah tata letak menjadi dua belas akan menjadi berlebihan, ketika yang kita butuhkan adalah seperempat.
Karena kita tahu kita hanya perlu memecah tata letak ini menjadi empat, kita dapat mengatur nilai variabel @default-total_cols
kita menjadi 4:
1 |
|
2 |
@default-total_cols: 4; |
Kemudian, ketika kita menggunakan mixin seperti yang kita miliki dalam contoh tata letak "klasik" kita, mixin mengasumsikan kamu ingin kolommu keluar dari kemungkinan empat kolom total. Jadi untuk mengatur elemen artikel kita menjadi tiga perempat lebar yang perlu kita lakukan adalah:
1 |
|
2 |
article { |
3 |
.Cols( 3 ); |
4 |
}
|
Kemudian untuk mengatur aside / sidebar menjadi seperempat lebar kita cukup menggunakan:
1 |
|
2 |
aside { |
3 |
.Cols( 1 ); |
4 |
}
|
Namun, jika kita memutuskan ingin menggunakan jumlah kolom total yang sama sekali berbeda, kita dapat melakukannya dengan mudah dengan melewatkan nilai yang berbeda melalui mixin .Cols()
.
Ini memungkinkan kita untuk mengubah lebar artikel dan menyisihkan elemen ke apa pun yang kita sukai dengan sangat mudah, misalnya:
1 |
|
2 |
article { |
3 |
.Cols( 7, 11 ); // sets this element to span 7 of a total 11 columns |
4 |
min-height: 500 * @toRems; |
5 |
background-color: #ddd; |
6 |
}
|
7 |
|
8 |
aside { |
9 |
.Cols( 4, 11 ); // sets this element to span 4 of a total 11 columns |
10 |
min-height: 500 * @toRems; |
11 |
background-color: #eee; |
12 |
}
|
Yang memberi kita:



Hal ini pada gilirannya membuatnya sangat mudah untuk menambahkan kolom tambahan, misalnya jika kita menambahkan elemen aside
kedua sebelum elemen article
di HTML kita, dan kemudian mengubah LESS kita menjadi yang berikut:
1 |
|
2 |
article { |
3 |
.Cols( 5, 9 ); |
4 |
min-height: 500 * @toRems; |
5 |
background-color: #ddd; |
6 |
}
|
7 |
|
8 |
aside { |
9 |
.Cols( 2, 9 ); |
10 |
min-height: 500 * @toRems; |
11 |
background-color: #eee; |
12 |
}
|
...kita akan mendapatkan:



Menambahkan Padding dan Margin
Setelah kamu mulai menambahkan konten di dalam wadahmu, tentu saja kamu ingin dapat mengontrol jarak di sekitarnya. Saat ini ketika kita menambahkan konten, konten tersebut akan berada di tepi:



Ada beberapa cara yang bisa kamu lakukan untuk mengendalikan jarakmu, dan mana yang terbaik untuk digunakan akan tergantung pada apa yang kamu coba capai dengan desain spesifik yang kamu buat.
Menambahkan Padding
Cara termudah untuk mengontrol jarak spasi adalah dengan menambahkan parameter padding sederhana ke mixin .Row()
dan .Cols()
.
Kode mixin kita akan disesuaikan sebagai berikut:
1 |
|
2 |
@default-padding: 0; |
3 |
|
4 |
.Row ( @width : @default-width; @padding: @default-padding; ) { |
5 |
max-width: @width; |
6 |
width: 100%; |
7 |
margin: 0 auto; |
8 |
padding: @padding; |
9 |
// clear at the end of container |
10 |
&:before,
|
11 |
&:after { |
12 |
content:""; |
13 |
display:table; |
14 |
}
|
15 |
&:after { |
16 |
clear:both; |
17 |
}
|
18 |
}
|
19 |
|
20 |
.Cols ( @colspan : @default-colspan; @total_cols : @default-total_cols; @padding: @default-padding; ) { |
21 |
width: ( @colspan * (100 / @total_cols) ) + 0%; |
22 |
float: left; |
23 |
padding: @padding; |
24 |
}
|
Sekarang kita bisa menambahkan padding ke element header, artikel, aside dan footer kita.
Catatan kita juga akan mengatur properti box-sizing
default di seluruh desain ke border-box
sehingga padding tidak dimasukkan dalam perhitungan browser dari lebar elemen:
1 |
|
2 |
* { |
3 |
box-sizing:border-box; |
4 |
-moz-box-sizing:border-box; |
5 |
}
|
6 |
|
7 |
header, footer { |
8 |
.Row ( |
9 |
@padding: 20 * @toRems; |
10 |
);
|
11 |
background-color: #ccc; |
12 |
min-height: 200 * @toRems; |
13 |
}
|
14 |
|
15 |
main { |
16 |
.Row;
|
17 |
background-color: #ccc; |
18 |
}
|
19 |
|
20 |
article { |
21 |
.Cols ( |
22 |
@colspan: 3; |
23 |
@padding: 10 * @toRems 20 * @toRems; |
24 |
);
|
25 |
min-height: 500 * @toRems; |
26 |
background-color: #ddd; |
27 |
}
|
28 |
|
29 |
aside { |
30 |
.Cols ( |
31 |
@colspan: 1; |
32 |
@padding: 10 * @toRems 20 * @toRems; |
33 |
);
|
34 |
min-height: 500 * @toRems; |
35 |
background-color: #eee; |
36 |
}
|
Ini sekarang memberi kita padding pada setiap konten kita:



Menambahkan Pembungkus Margin
Terkadang jarak spasi yang ingin kamu tambahkan ke desaimu ada di bagian luar elemen, bukan bagian dalam, misalnya ketika kamu ingin latar belakang situs ditampilkan di antara elemen. Untuk menyediakan ini, kita akan membuat beberapa tambahan lebih lanjut untuk mixin .Row()
dan .Cols()
.
Untuk memulainya, mari kita izinkan penambahan jarak spasi di atas dan di bawah elemen yang memiliki mixin .Row()
yang kita terapkan padanya. Ini mudah dilakukan hanya dengan mengganti nilai properti margin
kita yang ada dengan variabel yang dapat dikirim sebagai parameter melalui mixin.
1 |
|
2 |
@default-row_margin: 0 auto; |
3 |
|
4 |
.Row ( @width : @default-width; @padding: @default-padding; @margin: @default-row_margin; ) { |
5 |
max-width: @width; |
6 |
width: 100%; |
7 |
margin: @margin; |
8 |
padding: @padding; |
9 |
// clear at the end of container |
10 |
&:before,
|
11 |
&:after { |
12 |
content:""; |
13 |
display:table; |
14 |
}
|
15 |
&:after { |
16 |
clear:both; |
17 |
}
|
18 |
}
|
Perhatikan bahwa nilai default untuk margin baris masih diatur ke 0 auto
, jadi jika tidak ada parameter yang dilewati, mixin masih akan secara otomatis menengahkan elemen.
Namun jika kita meneruskan nilai @margin
melalui mixin:
1 |
|
2 |
header, footer { |
3 |
.Row ( |
4 |
@padding: 20 * @toRems; |
5 |
@margin: 10 * @toRems auto; |
6 |
);
|
7 |
background-color: #ccc; |
8 |
min-height: 200 * @toRems; |
9 |
}
|
... kita dapat menambahkan spasi vertikal seperti ini:



Selain itu, jika kamu memutuskan untuk tidak lagi menengahkan elemen, kamu juga dapat melakukan hal-hal seperti meneruskan nilai @margin
0 auto 0 0
untuk menyelaraskan ke kiri suatu elemen, atau 0 0 0 auto
untuk menyelaraskan ke kanan.
Menambahkan Saluran Kolom
Fitur umum lainnya dari sistem grid CSS adalah kemampuan untuk menambahkan saluran di antara kolom, semisal. Margin yang berlaku di antara setiap kolom, tetapi tidak di luar kolom terluar.
Sekali lagi, kita dapat menambahkan fungsionalitas ini dengan beberapa tambahan pada mixin Cols()
:
1 |
|
2 |
@default-gutter: 0; |
3 |
|
4 |
.Cols ( @colspan : @default-colspan; @total_cols : @default-total_cols; @padding: @default-padding; @gutter: @default-gutter; @edge: false; ){ |
5 |
@total_gutter: (@total_cols - 1) * @gutter; |
6 |
@spanned_gutters: (@colspan - 1) * @gutter; |
7 |
width: ( @colspan * ( (100 - @total_gutter) / @total_cols) ) + @spanned_gutters + 0%; |
8 |
float: left; |
9 |
padding: @padding; |
10 |
.IfEdge (@edge; @gutter); |
11 |
}
|
12 |
|
13 |
.IfEdge ( @edge; @gutter; ) when (@edge = false) { |
14 |
margin-right: @gutter + 0%; |
15 |
}
|
16 |
|
17 |
.IfEdge ( @edge; @gutter; ) when (@edge = true) { |
18 |
margin-right: 0; |
19 |
}
|
Mixin sekarang melakukan dua hal tambahan. Pertama, ia memeriksa suatu nilai melalui parameter @gutter
baru, dan faktor itu ke dalam perhitungan lebar untuk kolom.
Catatan: nilai @gutter
harus berupa angka yang dimaksudkan untuk digunakan sebagai nilai persen semisal. 2 untuk 2% saluran.
Kedua, memeriksa yang variabel @edge
baru untuk melihat apakah itu diatur ke true
atau false
. Jika @edge
diatur ke false
, nilai pada parameter @gutter
ditambahkan ke margin kanan sebagai persen. Jika @edge
diatur ke true
, margin kanan diatur ke 0
. Ini memungkinkamu untuk menentukan di mana kolom yang berada di tepi tata letamu dan karenanya seharusnya tidak memiliki saluran yang diterapkan.
Untuk menunjukkan efek perubahan ini pada mixin dengan lebih jelas, saya telah menambahkan dua elemen article
tambahan ke HTML kita. LESS untuk element article
dan aside
telah disesuaikan sebagai berikut:
1 |
|
2 |
article { |
3 |
.Cols ( |
4 |
@colspan: 1; |
5 |
@padding: 10 * @toRems 20 * @toRems; |
6 |
@gutter: 1; //include a gutter of 1% |
7 |
);
|
8 |
min-height: 500 * @toRems; |
9 |
background-color: #ddd; |
10 |
}
|
11 |
|
12 |
aside { |
13 |
.Cols ( |
14 |
@colspan: 1; |
15 |
@padding: 10 * @toRems 20 * @toRems; |
16 |
@gutter: 1; //include a gutter of 1% |
17 |
@edge: true; //this is the column on the edge so don't set a right margin |
18 |
);
|
19 |
min-height: 500 * @toRems; |
20 |
background-color: #eee; |
21 |
}
|
Yang sekarang memberkani kita:



Membiarkan kontrol atas margin vertikal pada kolom sekali lagi hanya masalah memasukkan beberapa parameter tambahan dalam mixin, menyesuaikannya dengan:
1 |
|
2 |
@default-margin_top: 0; |
3 |
|
4 |
@default-margin_bottom: 0; |
5 |
|
6 |
.Cols ( @colspan : @default-colspan; @total_cols : @default-total_cols; @padding: @default-padding; @gutter: @default-gutter; @edge: false; @margin_top : @default-margin_top; @margin_bottom : @default-margin_bottom; ){ |
7 |
@total_gutter: (@total_cols - 1) * @gutter; |
8 |
@spanned_gutters: (@colspan - 1) * @gutter; |
9 |
width: ( @colspan * ( (100 - @total_gutter) / @total_cols) ) + @spanned_gutters + 0%; |
10 |
float: left; |
11 |
padding: @padding; |
12 |
.IfEdge (@edge; @gutter; @margin_top; @margin_bottom; ); |
13 |
}
|
14 |
|
15 |
.IfEdge ( @edge; @gutter; @margin_top; @margin_bottom; ) when (@edge = false) { |
16 |
margin: @margin_top @gutter + 0% @margin_bottom 0; |
17 |
}
|
18 |
|
19 |
.IfEdge ( @edge; @gutter; @margin_top; @margin_bottom; ) when (@edge = true) { |
20 |
margin: @margin_top 0 @margin_bottom 0; |
21 |
}
|
Pengaturan margin atas dan bawah sekarang juga dapat dimasukkan saat menggunakan mixin .Cols()
, misalnya:
1 |
|
2 |
article { |
3 |
.Cols ( |
4 |
@colspan: 1; |
5 |
@padding: 10 * @toRems 20 * @toRems; |
6 |
@gutter: 1; |
7 |
@margin_top: 20 * @toRems; |
8 |
@margin_bottom: 30 * @toRems; |
9 |
);
|
10 |
min-height: 500 * @toRems; |
11 |
background-color: #ddd; |
12 |
}
|
13 |
|
14 |
aside { |
15 |
.Cols ( |
16 |
@colspan: 1; |
17 |
@padding: 10 * @toRems 20 * @toRems; |
18 |
@gutter: 1; |
19 |
@edge: true; |
20 |
@margin_top: 20 * @toRems; |
21 |
@margin_bottom: 30 * @toRems; |
22 |
);
|
23 |
min-height: 500 * @toRems; |
24 |
background-color: #eee; |
25 |
}
|
Yang akan menambahkan margin vertikal ke kolom seperti ini:



Bersarang dan Meningkatkan Kompleksitas Tata Letak
Kita sekarang akan menambahkan tingkat kerumitan lain pada tata letak contoh kita dengan menambah jumlah elemen article
menjadi enam dan menempatkannya di dalam suatu section
pembungkus elemen, lalu menerapkan mixin kita untuk membuat tata letak berikut:



Untuk mencapai tata letak ini, HTML sekarang diubah menjadi:
1 |
|
2 |
<!DOCTYPE html>
|
3 |
<html lang="en"> |
4 |
<head>
|
5 |
<meta charset="UTF-8"> |
6 |
<title>Classic Layout</title> |
7 |
<script type='text/javascript' src='js/modernizr.js'></script> |
8 |
<link rel="stylesheet" href="css/normalize.css"> |
9 |
<link rel="stylesheet" href="css/classiclayout.css"> |
10 |
</head>
|
11 |
<body>
|
12 |
<header>
|
13 |
<h1>Site Title</h1> |
14 |
</header>
|
15 |
<main>
|
16 |
<section>
|
17 |
<h1>Latest Articles</h1> |
18 |
<article>
|
19 |
<h1>Article Title</h1> |
20 |
<p>...</p> |
21 |
</article>
|
22 |
<article>
|
23 |
<h1>Article Title</h1> |
24 |
<p>...</p> |
25 |
</article>
|
26 |
<article>
|
27 |
<h1>Article Title</h1> |
28 |
<p>...</p> |
29 |
</article>
|
30 |
<article>
|
31 |
<h1>Article Title</h1> |
32 |
<p>...</p> |
33 |
</article>
|
34 |
<article>
|
35 |
<h1>Article Title</h1> |
36 |
<p>...</p> |
37 |
</article>
|
38 |
<article>
|
39 |
<h1>Article Title</h1> |
40 |
<p>...</p> |
41 |
</article>
|
42 |
</section>
|
43 |
<aside>
|
44 |
<p>...</p> |
45 |
</aside>
|
46 |
</main>
|
47 |
<footer>
|
48 |
<p>Example Footer</p> |
49 |
</footer>
|
50 |
</body>
|
51 |
</html>
|
Kode LESS yang kita gunakan untuk mengontrol tata letak kini telah diubah menjadi:
1 |
|
2 |
header, footer { |
3 |
.Row ( @padding: 20 * @toRems; @margin: 10 * @toRems auto; ); |
4 |
background-color: #ccc; |
5 |
min-height: 100 * @toRems; |
6 |
}
|
7 |
|
8 |
main { |
9 |
.Row;
|
10 |
}
|
11 |
|
12 |
section { |
13 |
.Cols ( @colspan: 3; @padding: 10 * @toRems 20 * @toRems; @gutter: 1; ); |
14 |
background-color: #ddd; |
15 |
}
|
16 |
|
17 |
aside { |
18 |
.Cols ( @colspan: 1; @padding: 10 * @toRems 20 * @toRems; @gutter: 1; @edge: true; ); |
19 |
min-height: 500 * @toRems; |
20 |
background-color: #eee; |
21 |
}
|
22 |
|
23 |
article { |
24 |
.Cols ( @colspan: 1; @total_cols: 3; @padding: 0 20 * @toRems 20 * @toRems 20 * @toRems; @margin_bottom: 20 * @toRems; @gutter: 2; ); |
25 |
background-color: #eee; |
26 |
&:nth-of-type(3n) { |
27 |
margin-right: 0; |
28 |
}
|
29 |
}
|
Untuk meringkas apa yang terkandung dalam kode LESS di atas:
Elemen section
diatur untuk mengambil tiga kolom dari total empat kolom default. Di sebelahnya ada elemen aside
, yang masih diatur ke satu kolom dari empat.
Elemen section
bertindak sebagai pembungkus untuk elemen article
. Karena elemen article
sekarang bersarang, mereka dapat memiliki semua lebar kolom baru yang diterapkan padanya, dan mereka masing-masing akan mengambil persentase interior elemen induknya. Dengan demikian, masing-masing diatur ke satu kolom dari tiga, dengan saluran 2%.
Setiap elemen article
ketiga diidentifikasi dengan menggunakan selektor: nth-of-type(3n)
dan diatur untuk tidak memiliki margin / saluran kanan.
Menyesuaikan ke Layar Kecil
Sebelumnya di artikel ini kita menunjukkan bagaimana responsif dasar ditambahkan dari kata yang dituju dengan menggunakan pendekatan ini. Hal lain yang akan kita lakukan secara berbeda untuk banyak orang lain adalah pendekatan kita untuk menambahkan breakpoint dan menentukan perilaku pada titik-titik ini.
Daripada mencoba mengidentifikasi dan menargetkan ukuran layar yang tepat dari berbagai perangkat, kita ingin membuat tata letak kami berfungsi pada setiap resolusi. Dengan cara ini kita menjadi perangkat yang independen.
Untuk mencapai ini, kita hanya akan memperkenalkan breakpoints pada lebar yang berubah-ubah ketika tata letak menjadi terlalu terjepit untuk dapat dibaca dengan nyaman, dan memodifikasi kolom untuk membuat konten dapat ditampilkan kembali.
Dalam hal tata letak ini, kita akan menambahkan kueri media berikut:
1 |
|
2 |
article { |
3 |
.Cols ( @colspan: 1; @total_cols: 3; @padding: 0 20 * @toRems 20 * @toRems 20 * @toRems; @margin_bottom: 20 * @toRems; @gutter: 2; ); |
4 |
background-color: #eee; |
5 |
@media (min-width: 68rem) { |
6 |
&:nth-of-type(3n) { |
7 |
margin-right: 0; |
8 |
}
|
9 |
}
|
10 |
}
|
11 |
|
12 |
@media (max-width: 68rem) { |
13 |
article { |
14 |
.Cols ( @colspan: 1; @total_cols: 2; @padding: 0 20 * @toRems 20 * @toRems 20 * @toRems; @margin_bottom: 20 * @toRems; @gutter: 2; ); |
15 |
@media (min-width: 53rem) { |
16 |
&:nth-of-type(2n) { |
17 |
margin-right: 0; |
18 |
}
|
19 |
}
|
20 |
}
|
21 |
}
|
22 |
|
23 |
@media (max-width: 53rem) { |
24 |
article { |
25 |
.Cols ( @colspan: 1; @total_cols: 1; @padding: 0 20 * @toRems 20 * @toRems 20 * @toRems; @margin_bottom: 20 * @toRems; @gutter: 0; ); |
26 |
}
|
27 |
section { |
28 |
.Cols ( @colspan: 2; @total_cols: 3; @padding: 10 * @toRems 20 * @toRems; @gutter: 1; ); |
29 |
}
|
30 |
aside { |
31 |
.Cols ( @colspan: 1; @total_cols: 3; @padding: 10 * @toRems 20 * @toRems; @gutter: 1; @edge: true; ); |
32 |
}
|
33 |
}
|
34 |
|
35 |
@media (max-width: 36rem) { |
36 |
section { |
37 |
.Cols ( @colspan: 1; @total_cols: 1; @padding: 10 * @toRems 20 * @toRems; @edge: true; ); |
38 |
}
|
39 |
aside { |
40 |
.Cols ( @colspan: 1; @total_cols: 1; @padding: 10 * @toRems 20 * @toRems; @edge: true; ); |
41 |
}
|
42 |
}
|
Seperti disebutkan di atas, breakpoint ditentukan berdasarkan kasus per kasus untuk setiap desain.
Untuk tujuan ini saya menggunakan plugin Firefox Firesizer untuk memberi saya tampilan seberapa lebar jendela browser saya dalam piksel. Saya secara bertahap mengecilkan lebar browser dan ketika saya mengidentifikasi suatu titik yang terlalu sempit saya membuat catatan pada lebar tampilannya.
Sayangnya LESS tidak akan membiarkan operasi apa pun terjadi pada nilai yang KITA gunakan untu media query kita, jadi kita tidak dapat melakukan sesuatu seperti @media (max-width: 1000 * @toRems)
.
Karenarn variabel @toRems
tidak dapat digunakan di sini untuk mengonversi nilai piksel, saya sebagai gantinya mengonversi lebar menjadi em menggunakan http://pxtoem.com/
Setelah mengonversi lebar yang diidentifikasi ke rem
, kita menambahkan breakpoint pada lebar itu dan menerapkan mixin .Cols()
baru ke elemen. Ini dapat mengubah nilai colspan
dan / atau nilai totalcols
yang tergantung pada apa yang terlihat paling baik pada lebar itu.
Bila diperlukan, kita juga membungkus setiap selektor nth-of-type()
dalam media query berbasis min-width
. Ini memastikan bahwa ketika tata letak semakin kecil dan jumlah kolom berkurang, kolom tepi diidentifikasi dengan benar karena setiap detik bukan setiap yang ketiga.
Sebagai contoh, pada breakpoint pertama 68rem
saya mengubah artikel dari masing-masing menjadi satu dari tiga kolom, menjadi salah satu dari dua kolom.
Saya juga menambahkan media query min-width: 68rem
di sekitar selektor :nth-of-type(3n)
sehingga hanya berlaku pada ukuran yang lebih besar dari 68rem
.
Lalu saya menambahkan selektor baru :nth-of-type (2n)
ke media query kita untuk ukuran lyang ebih rendah dari 68rem, yang akan mengidentifikasi setiap pos kedua sebagai tidak memerlukan saluran.
Perubahan ini membuat tata letak berikut saat viewport lebih kecil dari lebar 68rem
:



Pada breakpoint 53rem
berikutnya saya mengurangi jumlah kolom artikel lagi menjadi satu kolom, yaitu @colspan
1 pada @total_cols
1, dengan masing-masing artikel ditumpuk di atas yang lain.
Sekali lagi saya menambahkan media query min-width: 53rem
di sekitar selektor nth-of-type(2n)
yang kita tambahkan di atas, sehingga tidak lagi berlaku ketika artikel kita berkurang menjadi salah satu dari satu kolom.
Saya juga mengubah lebar section
dari 3/4 kolom menjadi 2/3, dan saya mengubah aside
dari 1/4 lebar menjadi 1 / 3. Ini memungkinkan sedikit lebih banyak ruang untuk bilah sisi sehingga tidak terlalu terjepit pada lebar ini.
Sekarang ketika desain dikurangi menjadi kurang dari 53rem
lebarnya terlihat seperti ini:



Akhirnya, pada 36rem
ketika tata letak menjadi terlalu sempit untuk mengakomodasi beberapa kolom sama sekali saya mengubah elemen section
dan aside
ke 1/1 kolom, yang mendorong aside
ke bawah di bawah elemen section
.
Tata letaknya sekarang terlihat seperti ini pada lebar kurang dari 36rem:



Membungkus
Kita telah melalui banyak detail di atas tentang cara kerja mixin .Row()
dan .Cols()
, untuk membermu pemahaman penuh sehingga kamu dapat membuat tambahan atau modifikasi lebih lanjut kepada mereka jika kamu mau. Namun, hasil akhir dari semua yang kita bahas sebenarnya adalah sistem tata letak yang super-sederhana dan mudah digunakan.
Dengan hanya menggunakan dua mixin, kini kamu dapat membuat tata letak yang sangat kompleks, fleksibel, dan dapat diskalakan tanpa batasan, dengan hanya menghasilkan CSS yang kamu butuhkan, dan menggunakan markup yang sangat semantik.
Kamu dapat menggunakan jumlah total kolom yang kamu inginkan untuk grid-mu, lebar setiap kolom dan lebar saluran. Ditambah, grid-grid mu yang bersarang tanpa batas.
Unduh salinan mixin-mu sendiri yang ditulis untuk tutorial ini dan cobalah untuk tata letak proyemu berikutnya!