CSS: panduan fungsi calc penuh ()

CSS memiliki fungsi khusus yang calc()digunakan untuk melakukan perhitungan sederhana. Berikut ini adalah contoh penggunaannya:

.main-content {
  /*  80px  100vh */
  height: calc(100vh - 80px);
}

Di sinicalc() Anda dapat bereksperimen dengan kode CSS yang digunakan . Penulis artikel, yang terjemahannya kami terbitkan hari ini, ingin berbicara tentang segala hal yang perlu diketahui tentang fungsi yang sangat berguna ini.





Fungsi Calc () dan nilai properti CSS


Satu-satunya tempat Anda dapat menggunakan fungsi calc()ini adalah dengan nilai properti CSS. Lihatlah contoh-contoh berikut di mana, menggunakan fungsi ini, kami menetapkan nilai berbagai properti.

.el {
  font-size: calc(3vw + 2px);
  width:     calc(100% - 20px);
  height:    calc(100vh - 20px);
  padding:   calc(1vw + 5px);
}

Fungsi calc()ini juga dapat digunakan untuk mengatur bagian terpisah dari properti:

.el {
  margin: 10px calc(2vw + 5px);
  border-radius: 15px calc(15px / 3) 4px 2px;
  transition: transform calc(1s - 120ms);
}

Fungsi ini bahkan dapat menjadi bagian dari fungsi lain yang bertanggung jawab untuk membentuk bagian dari properti tertentu! Sebagai contoh, di sini calc()digunakan untuk mengatur posisi perubahan warna gradien:

.el {
  background: #1E88E5 linear-gradient(
    to bottom,
    #1E88E5,
    #1E88E5 calc(50% - 10px),
    #3949AB calc(50% + 10px),
    #3949AB
  );
}

Fungsi calc () adalah alat untuk bekerja dengan properti numerik.


Harap dicatat bahwa dalam semua contoh di atas kami menggunakan fungsi calc()ketika bekerja dengan properti numerik. Kami juga akan berbicara tentang beberapa fitur bekerja dengan sifat numerik (mereka terkait dengan fakta bahwa kadang-kadang penggunaan unit pengukuran tidak diperlukan). Sekarang kita perhatikan bahwa fungsi ini dirancang untuk melakukan operasi dengan angka, dan bukan dengan string atau dengan sesuatu yang lain.

.el {
  /* ! */
  counter-reset: calc("My " + "counter");
}
.el::before {
  /* ! */
  content: calc("Candyman " * 3);
}

Ada banyak unit pengukuran yang dapat digunakan dalam CSS untuk menentukan ukuran elemen dan bagian mereka: px, %, em, rem, in, mm, cm, pt, pc, ex, ch, vh, vw, vmin, vmax. Semua unit ini dapat digunakan dengan fungsi tersebut calc().

Fungsi ini juga dapat bekerja dengan angka yang digunakan tanpa menentukan unit:

line-height: calc(1.2 * 1.2);

Ini juga dapat digunakan untuk menghitung sudut:

transform: rotate(calc(10deg * 5));

Fungsi ini juga dapat digunakan dalam kasus-kasus tersebut ketika tidak ada perhitungan yang dilakukan dalam ekspresi yang diteruskan ke sana:

.el {
  /*   ,    */
  width: calc(20px);
}

Calc () tidak dapat digunakan dalam kueri media


Meskipun fungsi ini dirancang untuk menetapkan nilai properti CSS, sayangnya tidak berfungsi di kueri media:

@media (max-width: 40rem) {
  /* 40rem   */
}

/*  ! */
@media (min-width: calc(40rem + 1px)) {
  /* ,  40rem */
}

Jika sekali konstruksi seperti itu terbukti bisa diterapkan, ini akan sangat baik, karena ini akan memungkinkan membuat kueri media yang saling eksklusif yang terlihat sangat logis (misalnya, yang ditunjukkan di atas).

Menggunakan unit yang berbeda dalam satu ekspresi


Penerimaan menggunakan satuan ukuran yang berbeda dalam satu ungkapan mungkin merupakan peluang yang paling berharga calc(). Serupa digunakan di hampir semua contoh di atas. Di sini, hanya untuk menarik perhatian Anda padanya, contoh lain yang menunjukkan penggunaan unit pengukuran yang berbeda:

/*      */
width: calc(100% - 20px);

Ungkapan ini berbunyi sebagai berikut: "Lebar sama dengan lebar elemen dari mana 20 piksel dikurangi."

Dalam situasi di mana lebar elemen dapat berubah, sama sekali tidak mungkin untuk menghitung nilai yang diinginkan sebelumnya, hanya menggunakan indikator yang dinyatakan dalam piksel. Dengan kata lain, Anda tidak dapat melakukan preprocess calc()menggunakan sesuatu seperti Sass dan mencoba untuk mendapatkan sesuatu seperti polyfill. Ya, ini tidak perlu, mengingat fakta bahwa browser mendukung dengancalc() sangat baik . Intinya di sini adalah bahwa perhitungan tersebut, di mana nilai-nilai yang dinyatakan dalam unit yang berbeda dicampur, harus dilakukan di browser (selama "eksekusi" halaman). Yaitu, kemampuan untuk melakukan perhitungan tersebut adalah nilai utama .calc()

Berikut adalah beberapa contoh penggunaan nilai yang diekspresikan dalam unit yang berbeda:

transform: rotate(calc(1turn + 45deg));

animation-delay: calc(1s + 15ms);

Anda mungkin dapat memproses ulang ekspresi ini, karena mereka mencampur nilai yang unitnya tidak terkait dengan apa pun yang ditentukan saat halaman berjalan di browser.

Perbandingan calc () dengan perhitungan preprocessor


Kami baru saja mengatakan bahwa fitur yang paling berguna adalah calc()tidak dapat menerima preprocessing. Tetapi preprocessing memberi pengembang beberapa fitur yang sesuai dengan kemampuan calc(). Misalnya, saat menggunakan Sass, Anda juga bisa menghitung nilai properti:

$padding: 1rem;

.el[data-padding="extra"] {
  padding: $padding + 2rem; //  3rem;
  margin-bottom: $padding * 2; //  2rem; 
}

Di sini, perhitungan dapat dibuat menunjukkan unit pengukuran, di sini Anda dapat menambahkan jumlah yang dinyatakan dalam unit pengukuran yang sama, Anda dapat mengalikan nilai-nilai tertentu dengan nilai-nilai yang unit pengukurannya tidak ditunjukkan. Tetapi tidak mungkin untuk melakukan perhitungan dengan nilai-nilai yang dinyatakan dalam unit pengukuran yang berbeda. Pembatasan menyerupai pembatasan diberlakukan pada perhitungan tersebut calc()(misalnya, angka-angka dimana sesuatu dikalikan atau dibagi harus menjadi nilai tanpa unit).

Mengungkapkan makna nilai numerik yang digunakan dalam CSS


Bahkan jika Anda tidak memanfaatkan peluang yang hanya dapat dicapai dengan bantuan calc(), fungsi ini dapat digunakan untuk mengungkapkan makna nilai yang digunakan dalam CSS. Misalkan Anda ingin nilai properti tepat 1/7 dari lebar elemen:

.el {
  /*   , */
  width: calc(100% / 7);

  /*   */
  width: 14.2857142857%;
}

Pendekatan ini mungkin berguna dalam sesuatu seperti semacam CSS-API gadungan:

[data-columns="7"] .col { width: calc(100% / 7); }
[data-columns="6"] .col { width: calc(100% / 6); }
[data-columns="5"] .col { width: calc(100% / 5); }
[data-columns="4"] .col { width: calc(100% / 4); }
[data-columns="3"] .col { width: calc(100% / 3); }
[data-columns="2"] .col { width: calc(100% / 2); }

Fungsi Operator Matematika dari calc ()


Ekspresi dievaluasi dengan bantuan calc()operator Anda dapat menggunakan +, -, *dan /. Namun dalam aplikasi mereka ada beberapa fitur.

Saat menambahkan ( +) dan mengurangi ( -), Anda harus menggunakan nilai dengan unit yang ditentukan

.el {
  /*  */
  margin: calc(10px + 10px);

  /*  */
  margin: calc(10px + 5);
}

Harap perhatikan bahwa penggunaan nilai yang salah mengarah pada fakta bahwa pengumuman tertentu juga menjadi salah.

Saat membagi ( /), unit pengukuran tidak harus diindikasikan pada angka kedua

.el {
  /*  */
  margin: calc(30px / 3);

  /*  */
  margin: calc(30px / 10px);

  /*  (   ) */
  margin: calc(30px / 0);
}

Saat mengalikan ( *), salah satu angka seharusnya tidak memiliki satuan ukuran:

.el {
  /*  */
  margin: calc(10px * 3);

  /*  */
  margin: calc(3 * 10px);

  /*  */
  margin: calc(30px * 3px);
}

Pentingnya ruang


Ruang yang digunakan dalam ekspresi adalah penting dalam operasi penjumlahan dan pengurangan:

.el {
  /*  */
  font-size: calc(3vw + 2px);

  /*  */
  font-size: calc(3vw+2px);

  /*  */
  font-size: calc(3vw - 2px);

  /*  */
  font-size: calc(3vw-2px);
}

Di sini sangat mungkin untuk menggunakan angka negatif (misalnya, dalam konstruksi seperti calc(5vw β€” -5px)), tetapi ini adalah contoh situasi di mana ruang tidak hanya diperlukan, tetapi juga berguna dalam hal kejelasan ekspresi.

Tab Atkins mengatakan kepada saya bahwa alasan mengapa operator penjumlahan dan pengurangan harus dipisahkan oleh spasi, pada kenyataannya, kekhasan ekspresi parsing. Saya tidak bisa mengatakan bahwa saya sepenuhnya memahami hal ini, tetapi, misalnya, parser memproses ekspresi 2px-3pxsebagai angka 2dengan satuan ukuranpx-3px. Dan tidak seorang pun akan membutuhkan unit pengukuran yang aneh. Ekspresi parsing dengan operator tambahan memiliki masalah sendiri. Misalnya, parser dapat menggunakan operator ini sebagai bagian dari sintaks yang digunakan untuk menggambarkan angka. Saya pikir diperlukan ruang untuk menangani sintaksis properti khusus ( --) dengan benar, tetapi bukan itu masalahnya.

Ketika mengalikan dan membagi ruang di sekitar operator tidak diperlukan. Tetapi saya percaya bahwa Anda dapat merekomendasikan penggunaan spasi dengan operator ini untuk meningkatkan keterbacaan kode, dan agar tidak melupakan spasi dan ketika memasukkan ekspresi yang menggunakan penambahan dan pengurangan.

Spasi yang memisahkan tanda kurung calc()dari ekspresi tidak memainkan peran apa pun. Ekspresi, jika diinginkan, bahkan dapat dipilih dengan pindah ke baris baru:

.el {
  /*  */
  width: calc(
    100%     /   3
  );
}

Benar, Anda harus berhati-hati di sini. calcSeharusnya tidak ada spasi antara nama fungsi ( ) dan braket pembuka pertama:

.el {
  /*  */
  width: calc (100% / 3);
}

Konstruksi bersarang: calc (calc ())


Saat bekerja dengan suatu fungsi calc(), Anda dapat menggunakan konstruksi bersarang, tetapi ini tidak benar-benar diperlukan. Ini mirip dengan menggunakan tanda kurung tanpa calc:

.el {
  width: calc(
    calc(100% / 3)
    -
    calc(1rem * 2)
  );
}

Tidak masuk akal untuk membangun konstruksi bersarang dari fungsi calc(), karena hal yang sama dapat ditulis ulang hanya menggunakan tanda kurung:

.el {
  width: calc(
   (100% / 3)
    -
   (1rem * 2)
  );
}

Selain itu, tanda kurung tidak diperlukan dalam contoh ini, karena aturan untuk menentukan prioritas operator diterapkan ketika menghitung ekspresi yang disajikan di sini. Pembagian dan perkalian dilakukan sebelum penambahan dan pengurangan. Hasilnya, kode dapat ditulis ulang seperti ini:

.el {
  width: calc(100% / 3 - 1rem * 2);
}

Tetapi jika kurung tambahan membuat kode lebih jelas, mereka dapat digunakan. Selain itu, jika tanpa tanda kurung, hanya berdasarkan prioritas operator, ekspresi akan dihitung secara tidak benar, maka ekspresi seperti itu membutuhkan tanda kurung:

.el {
  /* ,   , */
  width: calc(100% + 2rem / 2);

  /*     ,    */
  width: calc((100% + 2rem) / 2);
}

Properti CSS kustom dan calc ()


Kami sudah belajar tentang salah satu fitur hebat calc(), tentang perhitungan yang menggunakan nilai dengan unit yang berbeda. Fitur lain yang menarik dari fungsi ini adalah bagaimana itu dapat diterapkan dengan properti CSS khusus. Properti khusus dapat diberi nilai yang dapat digunakan dalam perhitungan:

html {
  --spacing: 10px;
}

.module {
  padding: calc(var(--spacing) * 2);
}

Saya yakin mudah membayangkan serangkaian gaya CSS di mana banyak pengaturan dilakukan di satu tempat dengan menetapkan nilai untuk properti CSS khusus. Nilai-nilai ini kemudian akan digunakan di seluruh kode CSS.

Properti khusus, di samping itu, dapat merujuk satu sama lain (perhatikan bahwa itu calc()tidak digunakan di sini). Nilai yang diperoleh dapat digunakan untuk mengatur nilai properti CSS lainnya (tapi di sini Anda calc()tidak bisa melakukannya tanpa).

html {
  --spacing: 10px;
  --spacing-L: var(--spacing) * 2;
  --spacing-XL: var(--spacing) * 3;
}

.module[data-spacing="XL"] {
  padding: calc(var(--spacing-XL));
}

Untuk beberapa hal ini mungkin terasa tidak nyaman, karena ketika mengakses properti khusus, Anda perlu mengingatnya calc(). Tapi saya menemukan ini menarik dalam hal keterbacaan kode.

Sumber properti khusus dapat berupa kode HTML. Terkadang ini bisa sangat berguna. Misalnya, dalam indeks Splitting.js ditambahkan ke kata dan simbol.

<div style="--index: 1;"> ... </div>
<div style="--index: 2;"> ... </div>
<div style="--index: 3;"> ... </div>
div {
  /*     HTML (   ) */
  animation-delay: calc(var(--index, 1) * 0.2s);
}

Menetapkan Unit ke Properti Kustom Setelah Mendeklarasikan Properti Ini


Misalkan kita berada dalam situasi di mana masuk akal untuk menulis angka tanpa satuan ukuran di properti kustom, atau dalam situasi di mana angka seperti itu akan nyaman, sebelum penggunaan yang sebenarnya, entah bagaimana mengkonversi tanpa menggunakan unit. Dalam kasus seperti itu, properti kustom dapat diberi nilai tanpa menentukan unit. Ketika akan perlu untuk mengubah angka ini menjadi yang baru, dinyatakan dalam satuan ukuran tertentu, itu dapat dikalikan dengan 1menunjukkan satuan pengukuran yang diinginkan:

html {
  --importantNumber: 2;
}

.el {
  /*    ,  ,        */
  padding: calc(var(--importantNumber) * 1rem);
}

Bekerja dengan bunga


Saat menggambarkan warna menggunakan format seperti RGB dan HSL, angka digunakan. Angka-angka ini dapat dikerjakan calc(). Misalnya, Anda dapat menetapkan beberapa nilai HSL dasar, dan kemudian mengubahnya sesuai kebutuhan ( berikut adalah contohnya):

html {
  --H: 100;
  --S: 100%;
  --L: 50%;
}

.el {
  background: hsl(
    calc(var(--H) + 20),
    calc(var(--S) - 10%),
    calc(var(--L) + 30%)
  )
}

Anda tidak dapat menggabungkan calc () dan attr ()


Fungsi CSS attr()sepertinya cukup menarik. Dan kebenarannya: Anda mengambil nilai atribut dari HTML, dan kemudian menggunakannya. Tapi…

<div data-color="red">...</div>
div {
  /*    */
  color: attr(data-color);
}

Sayangnya, fungsi ini tidak memahami "tipe" nilai. Akibatnya, attr()hanya cocok untuk bekerja dengan string dan untuk mengatur properti CSS menggunakannya content. Artinya, desain seperti itu ternyata cukup bekerja:

div::before {
  content: attr(data-color);
}

Saya mengatakan ini di sini karena seseorang mungkin ingin mencoba mengekstraksi angka attr()tertentu dari kode HTML dan menggunakannya dalam perhitungan:

<div class="grid" data-columns="7" data-gap="2">...</div>
.grid {
  display: grid;

  /*         */
  grid-template-columns: repeat(attr(data-columns), 1fr);
  grid-gap: calc(1rem * attr(data-gap));
}

Namun, hal baiknya adalah itu tidak terlalu penting, karena properti khusus di HTML bagus untuk menyelesaikan masalah seperti itu:

<div class="grid" style="--columns: 7; --gap: 2rem;">...</div>
.grid {
  display: grid;

  /* ! */
  grid-template-columns: repeat(var(--columns), 1fr);
  grid-gap: calc(var(--gap));
}

Alat peramban


Alat pengembang browser biasanya menampilkan ekspresi dengan calc()sama seperti yang dijelaskan dalam kode sumber CSS.


Alat Pengembang Firefox, tab Aturan

Jika Anda perlu mengetahui fungsi apa yang akan dihitungcalc(), Anda dapat merujuk ke tabComputed(tab ini dapat ditemukan di alat pengembang semua browser yang saya tahu). Di sana, nilai yang dihitung akan ditampilkancalc().


Tab yang Dihitung Alat Pengembang Chrome

Dukungan browser


Di sini Anda dapat mengetahui tentang dukungan calc()browser untuk fitur ini . Jika kita berbicara tentang browser modern, tingkat dukungan calc()lebih dari 97%. Jika Anda perlu mendukung browser yang cukup lama (seperti IE 8 atau Firefox 3.6), maka mereka biasanya melakukan ini: tambahkan calc()properti yang sama sebelum properti untuk menghitung nilai yang diatur dalam format yang dipahami oleh browser lama:

.el {
  width: 92%; /*   */
  width: calc(100% - 2rem);
}

Fungsi ini calc()memiliki banyak masalah yang diketahui, tetapi hanya browser lama yang menderita. Pada Caniuse dapat menemukan deskripsi dari 13 masalah tersebut. Inilah beberapa di antaranya:

  • Browser Firefox di bawah versi 59 tidak mendukung calc()fungsi yang digunakan untuk mengatur warna. Sebagai contoh: color: hsl(calc(60 * 2), 100%, 50%).
  • IE 9-11 tidak akan membuat bayangan yang ditentukan oleh properti box-shadowjika digunakan untuk menentukan nilai apa pun calc().
  • Baik IE 9-11 maupun Edge mendukung desain tampilan width: calc()ketika diterapkan pada sel tabel.

Contoh kehidupan


Saya bertanya kepada beberapa pengembang CSS tentang kapan terakhir kali mereka menggunakan fungsinya calc(). Jawaban mereka adalah pilihan kecil yang akan membantu semua orang untuk belajar tentang bagaimana programmer lain menggunakan calc()pekerjaan sehari-hari mereka.

  • Saya menggunakan calc()untuk menciptakan kelas pembantu untuk bidang manajemen: .full-bleed { width: 100vw; margin-left: calc(50% β€” 50vw); }. Saya dapat mengatakan bahwa ini calc()ada dalam 3 fitur CSS saya yang paling berguna.
  • Saya menggunakan fungsi ini untuk mengalokasikan ruang untuk "footer" tetap halaman.
  • calc() . , font-size, . font-size β€” calc() line-height. ( , calc() , , , rem em. , ).
  • , . . β€” : .margin { width: calc( (100vw β€” var(--content-width)) / 2); }.
  • calc() - , . : .drop-cap { --drop-cap-lines: 3; font-size: calc(1em * var(--drop-cap-lines) * var(--body-line-height)); }.
  • , .
  • , padding vw/vh.
  • Saya berlaku calc()untuk menghindari batasan background-position. Ini terutama berlaku untuk pembatasan penyesuaian posisi perubahan warna dalam gradien. Sebagai contoh, ini dapat digambarkan sebagai berikut: "posisi posisi perubahan warna, tidak mencapai 0.75embagian bawah."



Pembaca yang budiman! Apakah Anda menggunakan CSS calc()?

All Articles