Komponen · · 2 menit baca
Komponen company profile: kartu tim & timeline perusahaan
Grid tim dengan garis pemisah dari gap 1px (tanpa border ganda), timeline dari satu pseudo-element, avatar inisial dengan place-items, dan responsif tanpa media query — editor + preview live.
<div class="team">
<article class="member">
<span class="member__ava" aria-hidden="true">AN</span>
<b>Alif Nugraha</b>
<small>Founder & Lead Engineer</small>
</article>
<article class="member">
<span class="member__ava" aria-hidden="true">DW</span>
<b>Dewi Wulandari</b>
<small>Project Manager</small>
</article>
<article class="member">
<span class="member__ava" aria-hidden="true">BP</span>
<b>Bayu Pratama</b>
<small>Site Supervisor</small>
</article>
</div>
<ol class="timeline">
<li>
<span class="timeline__year">2015</span>
<p>Berdiri dengan 3 orang dan satu proyek kantor 120m².</p>
</li>
<li>
<span class="timeline__year">2019</span>
<p>Proyek ke-50 selesai; tim lapangan tetap pertama direkrut.</p>
</li>
<li>
<span class="timeline__year">2024</span>
<p>120+ proyek, ekspansi layanan ke MEP dan furniture custom.</p>
</li>
</ol>.team {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 1px;
background: #e4e4e7; /* garis pemisah = gap yang terlihat */
border: 1px solid #e4e4e7;
}
.member {
background: #fff;
padding: 18px 12px;
text-align: center;
}
.member__ava {
width: 44px;
height: 44px;
margin: 0 auto 10px;
border-radius: 999px;
background: #f0fdfa;
color: #0f766e;
display: grid;
place-items: center;
font-size: 13px;
font-weight: 600;
}
.member b { display: block; font-size: 13px; }
.member small { display: block; margin-top: 2px; font-size: 11px; color: #71717a; }
/* Timeline: satu garis vertikal dari ::before induknya */
.timeline {
position: relative;
margin: 24px 0 0;
padding: 0 0 0 26px;
list-style: none;
}
.timeline::before {
content: "";
position: absolute;
left: 5px;
top: 6px;
bottom: 6px;
width: 1px;
background: #e4e4e7;
}
.timeline li {
position: relative;
padding-bottom: 16px;
}
.timeline li::before {
content: "";
position: absolute;
left: -26px;
top: 5px;
width: 11px;
height: 11px;
border-radius: 999px;
background: #fff;
border: 2px solid #0d9488;
}
.timeline__year {
font-size: 11px;
letter-spacing: 0.14em;
color: #0d9488;
font-weight: 600;
}
.timeline p {
margin: 4px 0 0;
font-size: 13px;
line-height: 1.6;
color: #52525b;
}Preview
Dua section wajib di company profile: siapa orangnya, dan sudah berapa lama perusahaan berjalan. Keduanya di panel preview di atas — dan keduanya cuma CSS.
Garis pemisah dari gap, bukan dari border
Grid tim di contoh tidak memakai border di tiap kartu. Sebagai gantinya, container-nya berlatar abu-abu dan gap-nya 1px:
.team {
display: grid;
gap: 1px;
background: #e4e4e7; /* yang terlihat di celah = garis */
border: 1px solid #e4e4e7;
}
.member { background: #fff; }
Hasilnya garis pemisah yang sempurna: tidak ada border ganda di pertemuan dua kartu, tidak perlu :last-child untuk menghapus border terakhir, dan tetap rapi saat kartunya wrap ke baris berikutnya. Pola ini kupakai di hampir semua grid di situs ini.
Timeline: satu garis, satu pseudo-element
Timeline sering dibuat dengan library atau tumpukan <div>. Padahal cukup satu garis vertikal dari ::before induknya, plus satu titik dari ::before tiap item:
.timeline::before { /* garis vertikal */
content: "";
position: absolute;
left: 5px; top: 6px; bottom: 6px;
width: 1px;
background: #e4e4e7;
}
.timeline li::before { /* titik di tiap tahun */
content: "";
position: absolute;
left: -26px; top: 5px;
width: 11px; height: 11px;
border-radius: 999px;
background: #fff;
border: 2px solid #0d9488;
}
Kuncinya top: 6px; bottom: 6px pada garis — garis berhenti tepat di titik pertama dan terakhir, tidak menjulur keluar. Detail kecil ini yang membedakan timeline yang terlihat rapi dengan yang terlihat “belum jadi”.
Perhatikan juga elemennya: <ol>, bukan <div>. Riwayat perusahaan berurutan, dan urutan itu bermakna — screen reader akan menyebut “list, 3 items” dan menomorinya.
place-items: center — pemusatan dua baris
Avatar inisial dipusatkan dengan:
display: grid;
place-items: center;
Dua baris menggantikan trik lama line-height yang sama dengan tinggi elemen (rusak begitu teksnya dua karakter dengan ukuran font berbeda) atau position: absolute + transform: translate(-50%, -50%).
Responsif tanpa media query
repeat(auto-fit, minmax(140px, 1fr)) membuat jumlah kolom tim menyesuaikan sendiri: 3 kolom di desktop, 2 di tablet, 1 di HP — tanpa satu pun breakpoint ditulis. Coba perkecil jendela browser-mu dan lihat panel preview ikut menyesuaikan.
Pelajaran
- Latar container +
gap1px adalah cara termurah membuat garis pemisah grid yang selalu benar. - Pseudo-element menghemat puluhan elemen kosong di HTML — timeline, garis, dan badge hampir selalu bisa dibuat begitu.
- Pilih elemen berdasarkan maknanya (
<ol>untuk urutan), bukan berdasarkan tampilannya.
Mau fitur seperti ini dibangun untuk bisnismu?