Tentang konflik Sass dan fitur CSS yang relatif baru

Baru-baru ini, ada banyak fitur menarik di CSS, seperti Variabel CSS dan fitur baru . Meskipun semua ini dapat membuat hidup lebih mudah bagi desainer web, fitur-fitur ini dapat berinteraksi dengan preprosesor CSS seperti Sass dengan cara yang tidak terduga. Penulis materi, terjemahan yang kami terbitkan hari ini, akan berbicara tentang masalah apa yang dia hadapi, bagaimana dia menanganinya, dan mengapa dia percaya bahwa Sass masih mustahil untuk dilakukan tanpa.











Kesalahan



Jika Anda bereksperimen dengan CSS-fitur min()dan max()kemudian menggunakan unit yang berbeda dari pengukuran, kita bisa berhadapan dengan pesan error seperti ini: Incompatible units: vh and em.





Pesan error saat menggunakan unit yang berbeda dalam fungsi min () dan max ()



Pesan ini ditampilkan karena Sass memiliki fungsinya sendirimin().min()Akibatnya,fungsi CSSdiabaikan. Selain itu, Sass tidak dapat melakukan kalkulasi menggunakan unit yang tidak memiliki hubungan yang jelas di antara mereka.



Misalnya, hubungan antar unitdidefinisikancmdenganinbaik, sehingga Sass dapat menemukan hasil dari suatu fungsimin(20in, 50cm)dan tidak akan membuat kesalahan jika Anda menggunakan sesuatu seperti itu dalam kode Anda.



Hal yang sama terjadi dengan unit pengukuran lainnya. Sebagai contoh, semua unit sudut saling berhubungan:1turn,1radatau1gradselalu dikonversi ke nilai yang sama yang dinyatakan dalam satuan deg. Hal yang sama juga berlaku, misalnya, jika 1sselalu sama 1000ms. 1kHzselalu sama 1000Hz, 1dppxselalu sama 96dpi, 1inselalu sama 96px. Inilah sebabnya mengapa Sass dapat mengonversi nilai yang dinyatakan dalam unit ini satu sama lain dan mencampurnya dalam kalkulasi yang digunakan dalam berbagai fungsi, seperti fungsinya sendiri min().



Tetapi semuanya menjadi salah jika tidak ada hubungan yang jelas antara satuan pengukuran (seperti, misalnya, di atas, y emdan vh).



Dan ini terjadi tidak hanya saat menggunakan nilai yang dinyatakan dalam unit pengukuran yang berbeda. Mencoba menggunakan fungsi secara calc()internalmin()juga menghasilkan kesalahan. Jika Anda mencoba untuk min(), meletakkan sesuatu seperti calc(20em + 7px), ini akan menampilkan kesalahan ini: calc(20em + 7px) is not a number for min.





Pesan kesalahan terjadi ketika Anda mencoba untuk menggunakan calc () di min ()



Masalah lain terjadi dalam situasi ketika mencoba untuk menggunakan CSS-variabel atau output dari fungsi CSS-matematika (seperticalc(),min(),max()) di CSS-seperti filterinvert().



Berikut adalah pesan kesalahan yang mungkin Anda lihat dalam keadaan serupa:$color: 'var(--p, 0.85) is not a color for invert





Menggunakan var () di filter: invert () hasil dalam kesalahan



Hal yang sama terjadi dengangrayscale():$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.





Menggunakan calc () di filter: grayscale () menghasilkan kesalahan



desainfilter: opacity()juga dikenakan isu-isu serupa:$color: ‘var(--p, 0.8)‘ is not a color for opacity.





Menggunakan var () di filter: opacity () menghasilkan kesalahan



, tetapi fungsi lain yang digunakanfilter, termasuksepia(),blur(),drop-shadow(),brightness(),contrast()danhue-rotate(), bekerja dengan CSS-variabel adalah normal!



Ternyata penyebab masalah ini mirip dengan yang mempengaruhi fungsimin()danmax(). The Sass ada built-in fungsisepia(),blur(),drop-shadow(),brightness(),contrast(),hue-rotate(). Tapi itu memiliki fungsi grayscale () , invert () dan opacity () sendiri . Argumen pertama untuk fungsi ini adalah nilainya$color. Kesalahan muncul karena fakta bahwa ketika menggunakan konstruksi yang bermasalah, Sass tidak menemukan argumen seperti itu.



Untuk alasan yang sama, masalah muncul saat menggunakan variabel CSS yang mewakili setidaknya dua hsl()atau- hsla()nilai.





Kesalahan saat menggunakan var () dalam color: hsl ()



Di sisi lain, tanpa menggunakan Sass, sebuah konstruksicolor: hsl(9, var(--sl, 95%, 65%))adalah CSS yang benar dan berfungsi sempurna.



Hal yang sama berlaku untuk fungsi sepertirgb()danrgba():





Kesalahan menggunakan var () dalam color: rgba ()



Selain itu, jika Anda mengimpor Kompas dan mencoba menggunakan variabel CSS di dalamnyalinear-gradient()atauradial-gradient(), Anda mungkin mengalami kesalahan lain. Tetapi, pada saat yang sama,conic-gradient()Anda dapat menggunakan variabel tanpa masalah (tentu saja, jika browser mendukung fungsi ini).





Kesalahan saat menggunakan var () di latar belakang: gradien-linier ()



Alasan untuk masalah ini terletak pada fakta bahwa Kompas memiliki gradien linier () danradial-gradient()fungsinya sendiri, tetapi fungsinyaconic-gradient()tidak pernah ada.



Secara umum, semua masalah ini berasal dari fakta bahwa Sass dan Compass memiliki fungsi masing-masing, yang namanya sama dengan yang ada di CSS. Baik Sass dan Compass, saat memenuhi fungsi ini, yakin bahwa kami akan menggunakan implementasi mereka sendiri dari fungsi ini, dan bukan yang standar.



Ini penyergapan!



Larutan



Masalah ini dapat diselesaikan dengan mengingat bahwa Sass peka huruf besar kecil, tetapi CSS tidak.



Ini berarti Anda dapat menulis sesuatu seperti ini Min(20em, 50vh)dan Sass tidak mengenali fungsinya sendiri dalam konstruksi itu min(). Tidak ada kesalahan yang akan dibuat. Konstruksi ini akan menjadi CSS yang dibentuk dengan baik yang bekerja persis seperti yang diharapkan. Demikian pula, untuk menyingkirkan masalah dengan fungsi lainnya bisa, non-standar cara dengan menulis nama mereka: HSL(), HSLA(), RGB(), RGBA(), Invert().



Dalam hal gradien, saya biasanya menggunakan bentuk ini: linear-Gradient()dan radial-Gradient(). Saya melakukan ini karena notasi ini dekat dengan nama yang digunakan dalam SVG, tetapi dalam situasi ini, nama lain yang serupa yang menyertakan setidaknya satu huruf besar akan berfungsi.



Mengapa semua komplikasi ini?



Hampir setiap kali saya tweet sesuatu tentang Sass, saya mendapatkan kuliah tentang bagaimana sekarang Anda memiliki variabel CSS, Anda tidak perlu menggunakan Sass lagi. Saya memutuskan bahwa saya harus menjawab ini dan menjelaskan alasan ketidaksetujuan saya dengan gagasan ini.



Pertama, saya akan mencatat bahwa saya menemukan Variabel CSS sangat berguna, dan saya telah menggunakannya untuk berbagai tugas selama tiga tahun terakhir. Tetapi saya kira Anda perlu ingat bahwa menggunakannya memiliki dampak kinerja. Dan mencari masalah dalam labirin panggilancalc()bisa menjadi pengalaman yang paling tidak menyenangkan. Alat pengembang browser standar belum begitu bagus dalam hal ini. Saya mencoba untuk tidak terbawa oleh penggunaan variabel CSS, agar tidak masuk ke dalam situasi di mana kelemahan mereka menunjukkan diri mereka lebih dari keuntungan mereka.





Tidak mudah untuk memahami seperti apa hasil evaluasi ekspresi calc (). Secara



umum, jika variabel digunakan sebagai konstanta, variabel tidak berubah dari elemen ke elemen, atau dari status ke status (dan dalam kasus seperti itu, variabel CSS harus menggunakan diperlukan ), atau jika variabel tidak mengurangi jumlah CSS yang dikompilasi (menyelesaikan masalah pengulangan yang dibuat oleh prefiks), maka saya akan menggunakan variabel Sass.



Kedua, mempertahankan variabel selalu menjadi alasan yang agak kecil di antara alasan saya menggunakan Sass. Ketika saya mulai menggunakan Sass pada paruh kedua tahun 2012, saya melakukannya terutama untuk loop. Untuk fitur yang masih hilang di CSS. Meskipun saya telah memindahkan beberapa logika perulangan ke preprocessor HTML (karena ini mengurangi jumlah kode yang dihasilkan dan menghindari kebutuhan untuk memodifikasi HTML dan CSS), saya masih menggunakan loop Sass dalam banyak kasus. Ini termasuk membuat daftar nilai, membuat nilai untuk menyesuaikan gradien, membuat daftar titik saat bekerja dengan suatu fungsi polygon(), membuat daftar transformasi, dan sebagainya.



Di bawah ini adalah contoh dari apa yang akan saya lakukan sebelumnya saat membuat beberapa elemen HTML menggunakan preprocessor. Praprosesor mana yang tidak terlalu penting, tetapi saya memilih Pug:



- let n = 12;

while n--
  .item


Kemudian saya akan membuat variabel $ndi Sass (dan variabel ini harus memiliki nilai yang sama seperti di HTML) dan memulai loop menggunakannya, di mana saya akan menghasilkan transformasi yang digunakan untuk memposisikan masing-masing elemen:



$n: 12;
$ba: 360deg/$n;
$d: 2em;

.item {
  position: absolute;
  top: 50%; left: 50%;
  margin: -.5*$d;
  width: $d; height: $d;
  /*    */

  @for $i from 0 to $n {
    &:nth-child(#{$i + 1}) {
      transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
      &::before { content: '#{$i}' }
    }
  }
}


Kelemahan dari ini adalah bahwa saya harus mengubah nilai di kedua kode Pug dan kode Sass jika jumlah elemen berubah. Selain itu, ada banyak pengulangan dalam kode.





Kode CSS yang dihasilkan dari kode di atas



Sekarang saya mengambil pendekatan yang berbeda. Yaitu, dengan menggunakan Pug, saya menghasilkan indeks sebagai properti khusus dan kemudian menggunakannya dalam deklarasitransform.



Inilah kode yang direncanakan Pug untuk dilakukan:



- let n = 12;

body(style=`--n: ${n}`)
  - for(let i = 0; i < n; i++)
    .item(style=`--i: ${i}`)


Inilah kode Sass:



$d: 2em;

.item {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -.5*$d;
  width: $d;
  height: $d;
  /*    */
  --az: calc(var(--i)*1turn/var(--n));
  transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
  counter-reset: i var(--i);

  &::before { content: counter(i) }
}


Anda dapat bereksperimen dengan kode ini di sini.





Elemen yang Dihasilkan dan Ditata Menggunakan Loop



Mengambil pendekatan ini secara signifikan mengurangi jumlah CSS yang dibuat secara otomatis.





CSS dihasilkan dari kode di atas



Tetapi jika Anda ingin membuat sesuatu seperti pelangi, Anda tidak dapat melakukannya tanpa Sass loop.



@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
  $unit: 360/$n;
  $s-list: ();

  @for $i from 0 through $n {
    $s-list: $s-list, hsl($i*$unit, $sat, $lum)
  }

  @return $s-list
}

html { background: linear-gradient(90deg, get-rainbow()) }


Berikut adalah versi kerja dari contoh ini.





Latar belakang multi-warna



Tentu saja, ini dapat dibuat menggunakan variabel Pug, tetapi pendekatan ini tidak memiliki keunggulan dibandingkan dengan sifat dinamis variabel CSS, dan tidak akan mengurangi jumlah kode yang dikirimkan ke browser. Akibatnya, tidak masuk akal bagi saya untuk melepaskan apa yang biasa saya lakukan.



Saya sering menggunakan fungsi matematika bawaan Sass (dan Kompas), seperti fungsi trigonometri. Saat ini, fitur ini adalah bagian dari spesifikasi CSS , tetapi belum semua browser mendukungnya. Sass tidak memiliki fungsi ini, tetapi Kompas memilikinya, itulah mengapa saya sering menggunakan Kompas.



Dan tentu saja saya bisa menulis fungsi saya sendiri semacam ini di Sass. Saya melakukan ini di awal, sebelum Kompas memiliki dukungan untuk fungsi trigonometri terbalik. Saya sangat membutuhkan fungsi-fungsi ini, jadi saya menulisnya sendiri menggunakan seri Taylor . Namun belakangan ini, fitur-fitur ini ada di Kompas. Mereka lebih baik dan lebih produktif daripada yang saya tulis sendiri.



Fungsi matematika sangat penting bagi saya karena saya seorang programmer, bukan seniman. Nilai-nilai dalam kode CSS saya biasanya dihasilkan dari perhitungan matematis. Ini bukanlah beberapa "angka ajaib", atau sesuatu yang memainkan peran estetika murni. Contoh penggunaannya adalah membuat daftar poligon beraturan atau semu-reguler untukclip-path... Ini digunakan, misalnya, saat membuat sesuatu seperti avatar atau stiker, yang bentuknya berbeda dari persegi panjang.



Pertimbangkan poligon beraturan yang simpulnya terletak pada lingkaran. Menyeret penggeser pada contoh berikut, yang dapat kita eksperimen di sini , memungkinkan kita untuk melihat di mana titik-titik ditempatkan untuk bentuk dengan jumlah simpul yang berbeda.





Bentuk tiga titik



Seperti inilah tampilan kode Sass:



@mixin reg-poly($n: 3) {
  $ba: 360deg/$n; //  
  $p: (); //   ,  

  @for $i from 0 to $n {
    $ca: $i*$ba; //  
    $x: 50%*(1 + cos($ca)); //  x  
    $y: 50%*(1 + sin($ca)); //  y  
    $p: $p, $x $y //       
  }

  clip-path: polygon($p) //       clip-path 
}


Harap dicatat bahwa kami menggunakan loop dan konstruksi lain di sini, yang sangat tidak nyaman untuk digunakan dengan CSS murni.



Versi yang sedikit lebih maju dari contoh ini mungkin melibatkan pemutaran poligon dengan menambahkan offset ( $oa) yang sama ke sudut yang sesuai dengan setiap simpul. Hal tersebut dapat dilihat pada contoh berikut . Bintang dibuat di sini, yang disusun dengan cara yang sama, tetapi selalu memiliki jumlah simpul genap. Selain itu, setiap simpul dengan indeks ganjil terletak pada sebuah lingkaran yang jari-jarinya lebih kecil dari lingkaran utama ( $f*50%).





Bintang



Anda dapat membuat bintang yang begitu menarik.





Bintang



Anda dapat membuat stiker dengan garis tepi (border) yang dibuat menggunakan templat yang tidak biasa. Dalamcontoh ini , stiker dibuat dari satu elemen HTML, dan template yang digunakan untuk penyesuaianborderdibuat menggunakanclip-pathloop Sass dan matematika. Padahal, banyak sekali perhitungan di sini.





Stiker dengan Garis Tepi yang Rumit Contoh



lainnyaadalah bagaimana membuat latar belakang untuk kartu. Di sini, dalam satu lingkaran, menggunakan operator modulus dan fungsi eksponensial, latar belakang dibuat dengan meniru efek dithering.





Efek Dithering



Di sini juga, Variabel CSS banyak digunakan



Selanjutnya, Anda dapat memikirkan untuk menggunakan mixin untuk menghindari keharusan menulis deklarasi yang sama berulang kali saat menata sesuatu seperti slider . Browser yang berbeda menggunakan elemen semu yang berbeda untuk mengatur gaya komponen internal dari kontrol tersebut, jadi untuk setiap komponen Anda perlu menentukan gaya yang mengontrol penampilannya menggunakan elemen semu yang berbeda.



Sayangnya, dalam CSS, meskipun terdengar menggoda, Anda tidak dapat meletakkan sesuatu seperti kode berikut:



input::-webkit-slider-runnable-trackinput::-moz-range-trackinput::-ms-track { /*   */ }


Ini tidak akan berhasil. Seluruh rangkaian aturan ini diabaikan jika setidaknya satu pemilih tidak dikenali. Dan, karena tidak ada browser yang mengetahui keberadaan ketiga penyeleksi dalam contoh ini, gaya ini tidak akan diterapkan di browser mana pun.



Jika Anda ingin penataannya berfungsi, Anda perlu melakukan sesuatu seperti ini:



input::-webkit-slider-runnable-track { /*   */ }
input::-moz-range-track { /*   */ }
input::-ms-track { /*   */ }


Tetapi ini dapat menyebabkan gaya yang sama muncul tiga kali dalam kode. Dan jika Anda perlu, katakanlah, untuk mengubah trackproperti background, ini berarti Anda harus mengedit gaya in ::-webkit-slider-runnable-track, in, ::-moz-range-trackdan in ::-ms-track.



Satu-satunya solusi yang masuk akal untuk masalah ini adalah dengan menggunakan mixin. Gaya diulangi dalam kode yang dikompilasi, karena kita tidak dapat melakukannya tanpanya, tetapi sekarang kita, setidaknya, tidak perlu memasukkan kode yang sama tiga kali di editor.



@mixin track() { /*   */ }

input {
  &::-webkit-slider-runnable-track { @include track }
  &::-moz-range-track { @include track }
  &::-ms-track { @include track }
}


Hasil



Kesimpulan utama yang bisa saya tarik adalah ini: Sass in adalah sesuatu yang tidak dapat kita lakukan tanpanya.



Apakah Anda menggunakan Sass?






All Articles