Bayangkan layout dengan sidebar tetap 180px di kiri. Konten di sebelahnya harus mengisi sisa ruang, tetapi persen tidak bisa berhitung: 100% berarti seluruh lebar induk, dan tidak ada operator pengurangan pada 100% - 180px dalam penulisan biasa. Fungsi calc() melengkapi kekurangan itu: kita dapat menulis ekspresi hitungan yang mencampur satuan, dan browser yang menyelesaikannya. Pada chapter ini kita mempelajari aturan operatornya, membangun layout sidebar nyata, dan mencampur calc() dengan var().

Aturan Penulisan calc() #

calc() menerima satu ekspresi yang boleh memuat +, -, *, dan /:

css
.konten {
  width: calc(100% - 180px);
}

Nilai di dalam calc() boleh mencampur satuan apa pun yang kompatibel: persen dengan piksel, rem dengan vw, dan seterusnya. Hasil calc(100% - 180px) adalah lebar induk dikurangi 180px, dan nilainya dihitung ulang setiap kali induk berubah.

Setiap operator punya aturannya sendiri, dan aturan ini bersifat wajib:

OperatorAturanContoh benar
+ dan -spasi WAJIB di kedua sisicalc(100% - 180px)
*salah satu sisi harus angka tanpa satuancalc(2rem * 3)
/sisi kanan harus angka tanpa satuancalc(100% / 3)

Spasi pada + dan - bukan sekadar kerapian, melainkan syarat sintaks. Tanpa spasi, calc(100%-180px) bisa terbaca sebagai nilai negatif -180px yang menempel pada 100%, sehingga browser menganggap deklarasi tidak valid dan mengabaikannya. Untuk * dan / spasi tidak diwajibkan, tetapi menuliskannya tetap membuat kode lebih mudah dibaca.

Ekspresi calc() juga boleh bersarang, misalnya calc(calc(100% - 40px) / 2); dalam praktik cukup ditulis calc((100% - 40px) / 2) karena tanda kurung sudah menjelaskan urutan hitungan. Urutan pengerjaannya mengikuti matematika biasa: * dan / dihitung sebelum + dan -, dan tanda kurung mengubah urutan itu. Bila ragu, tambahkan tanda kurung — tidak ada penalti selain kejelasan.

Ekspresi calc() tidak terbatas pada property; fungsi ini juga valid di dalam kondisi media query, sehingga ambang breakpoint pun bisa dihitung:

css
@media (min-width: calc(420px + 20vw)) {
  .katalog {
    display: grid;
  }
}

Layout grid pada .katalog baru aktif ketika lebar viewport melewati angka hasil perhitungan tersebut. Pola ini jarang dibutuhkan, tetapi berguna bila ambang tata letak memang diturunkan dari nilai yang sudah ada.

Layout Nyata: Sidebar Tetap, Konten Mengisi Sisa #

Kembali ke kasus pembuka. Dua elemen berikut nantinya kita susun berdampingan dengan Flexbox pada section layout; untuk sekarang fokus kita adalah hitungan lebarnya:

css
.sidebar {
  width: 180px;
}

.konten {
  /* mengisi sisa ruang di samping sidebar 180px */
  width: calc(100% - 180px);
}

Sidebar tetap dan konten yang mengisi sisa ruang:

Bila kita mengubah lebar sidebar, cukup satu angka yang disunting dan hitungan calc() mengikuti. Coba bayangkan mengganti 180px di hitungan itu dengan var(--lebar-sidebar) seperti pada contoh sebelumnya.

Nilai lain yang populer adalah tipografi dan jarak yang bergerak mengikuti layar:

css
h1 {
  font-size: calc(1rem + 1vw);
}

.wadah-artikel {
  padding: calc(1rem + 2vh) 1.5rem;
}

Demo berikut menyandingkan judul berukuran tetap dengan judul calc(1rem + 1vw):

Perhatikan bahwa hasil calc(1rem + 1vw) tidak punya batas atas — pada layar sangat lebar judul bisa membengkak. Di chapter berikutnya kita menjepitnya dengan fungsi clamp().

calc() dan var() #

Kombinasi paling berguna adalah calc() dengan custom properties yang kita kenal pada chapter Nilai CSS. Satu angka sumber, banyak perhitungan yang mengikutinya:

css
:root {
  --lebar-sidebar: 180px;
}

.konten {
  width: calc(100% - var(--lebar-sidebar));
}

Mengganti --lebar-sidebar cukup dilakukan di satu tempat, dan seluruh perhitungan di seluruh halaman ikut terbarui. Pola ini menjadi dasar sistem design token sederhana.

Selain calc(), CSS juga menyediakan fungsi matematika lain seperti round(), mod(), dan rem() untuk pembulatan dan sisa pembagian; keduanya sudah didukung browser modern dan cukup kita ingat sebagai perluasan keluarga fungsi matematika ini.

Kesalahan Umum #

KesalahanAkibatPerbaikan
calc(100%-180px) tanpa spasideklarasi dianggap tidak valid dan diabaikanberi spasi di kedua sisi + dan -
calc(100% / 180px)pembagian oleh nilai bersatuan tidak validbagi hanya dengan angka tanpa satuan
calc(0 + 100px)angka tanpa satuan tidak bisa dijumlah dengan panjangtulis calc(0px + 100px)

Ringkasan #

calc() memungkinkan CSS berhitung: mencampur persen dengan piksel, rem dengan vw, dan menyisipkan custom properties di dalamnya. Aturan wajibnya hanya sedikit — spasi pada + dan -, serta angka tanpa satuan pada * dan /. Satu kelemahan calc() adalah hasilnya tak terbatas: calc(1rem + 1vw) akan terus tumbuh mengikuti layar. Chapter berikutnya memperkenalkan min(), max(), dan clamp(), tiga fungsi yang memberi batas pada perhitungan seperti ini.