Bagaimana kami berteman dengan SCSS dengan Variabel CSS menggunakan Tema UI Kit


Halo semuanya, nama saya Vitalik, saya adalah pengembang senior front-end di Skyeng. Tim kami membuat platform Vimbox online untuk belajar bahasa Inggris. Sekitar setahun yang lalu, desainer dan saya menyelesaikan kit UI kecil yang mencabut kekacauan dalam antarmuka dan basis kode.


Ternyata kami bukan satu-satunya di perusahaan yang menginginkan kit UI, dan tim lain mulai mendatangi kami untuk meminta nasihat "bagaimana menulis sendiri". Kami berhasil mencegah mereka dari usaha ini, berjanji untuk menggerogoti usaha kami sendiri - ini menghemat ratusan jam perkembangan perusahaan. Memilih solusi, kami memeriksa Bahan Sudut, rakitan khusus, dan Variabel CSS dan akhirnya memilih yang terakhir, meskipun kompatibilitasnya lemah dengan SCSS, fondasi perangkat UI yang ada. Di bawah potongan - detail dari apa yang kami lakukan.



Masalah


Kit UI pertama terdiri dari font, palet, seperangkat elemen untuk membuat formulir (input, tombol, dll.), Sistem untuk mengelola ikon svg. Popup dan tooltip berdasarkan bahan Angular juga diterapkan. Itu dipenjara karena hanya bekerja dengan Vimbox "klasik": banyak hal yang sengaja dijahit dengan ketat dan tidak memungkinkan perubahan dari luar. Dan Skyeng mulai memiliki produk baru pada platform yang sama, misalnya, untuk anak-anak.


Pengembang arah baru, mengetahui bahwa kami memiliki sesuatu, datang untuk meminta saran. Selain itu, yang mengejutkan kami, mereka sudah datang dengan tata letak kit UI mereka: mereka akan mengembangkan solusi mereka dari awal, karena mereka membutuhkan tampilan berbeda untuk komponen. Jelas bahwa ada sesuatu yang salah, dan kami mengusulkan untuk memperbaiki perpustakaan kami, menambahkan kemungkinan bertema.


Argumennya sederhana: merancang kit UI kami membutuhkan 200 jam desain UX dan lebih dari 500 jam pengembangan. Ini adalah waktu yang diperlukan untuk membuat sistem font, warna, dan sekitar 10 komponen dasar. Karenanya, jika Anda menulis perpustakaan terpisah untuk setiap produk, perusahaan akan menghabiskan waktu pengembangan N * 500 jam. Kami berpikir bahwa meningkatkan kit UI kami akan lebih murah, ditambah langkah ini tidak harus diulang untuk setiap produk.


Argumen kami diterima, bidang terkait sepakat untuk menunggu, dan kami berangkat untuk mencari solusi teknis.


Sumber data


Alat kami: Angular, SCSS.


Kami hanya mendukung browser modern dan, dengan beberapa keterbatasan, IE11. Yang membuat hidup lebih mudah.


Semua komponen kit UI kami dipenuhi gaya umum yang kami susun di UI kit.var.scss sebagai konstanta SCSS:


 @mixin fontSizeXl { @include fontSize(18px, 26px); } $colorSkillListening: #9679e0; $colorSkillListeningText: #7754d1; $colorSkillListeningBackground: mix($colorSkillListening, #ffffff, 16%); $colorSkillListeningBackgroundHover: mix($colorSkillListening, #ffffff, 8%); 

Tantangan


  • Semua produk baru dirangkai dari elemen-elemen yang ada yang ada di Vimbox "dewasa" - ruang kelas, akun pribadi, dll.
  • Desainer harus memiliki kebebasan luas untuk mengimplementasikan ide-ide kreatif, fitur-fitur khas dan persyaratan khusus produk baru.
  • Pada saat yang sama, kontinuitas tetap, yaitu tidak peduli seberapa asam warna dan font gila yang diciptakan desainer, kepemilikan hasil karyanya ke ekosistem Skyeng tetap jelas.
  • Semua ini ditambahkan ke kit UI yang ada, sambil tetap mempertahankan semua kelebihannya.

Ayo pergi!


Jadi, hasilnya diharapkan dari kita kemarin, kita harus cepat melakukan tinjauan teknis dan mendiskusikan opsi. Pada pertemuan pertama, kami mengidentifikasi lingkaran solusi yang mungkin:


Bahan sudut


Kami tidak ingin menulis sepeda, jadi kami beralih dulu ke Bahan Angular. Dalam komponen, gaya dinamis dipindahkan ke file {component}-theme.scss . Gaya-gaya ini terikat pada pemilih global komponen.


pluskontra
tidak perlu menambahkan teknologi baru ke proyekperlu melakukan perubahan pada setiap komponen
jumlah pekerjaan terbesar
harus mengorbankan enkapsulasi gaya

Variabel CSS


Kami memiliki alasan kuat untuk mencoba Variabel CSS yang trendi. Rencananya adalah untuk mentransplantasikan bagian khusus dari kit UI ke Variabel CSS. Komponen menggunakan konstanta SCSS yang sama, tetapi bukannya nilai-nilai spesifik, vars CSS ditulis di dalamnya.


pluskontra
memiliki ruang lingkupharus menambahkan polyfill untuk IE
teknologi browser asli (kecuali IE)kita tidak akan dapat menggunakan fungsi SCSS
membuka kemungkinan menggunakan vars CSS dalam tugas lain

Membangun kustom


Kami menyukai solusi sederhana, mengapa tidak mencoba mengubah perakitan? Setiap tim membuat file sendiri dengan pengaturan tema. Saat menyusun untuk semua tema khusus, bundel terpisah dengan tema mereka sendiri dibuat.


pluskontra
tidak perlu mengubah kode perpustakaankonfigurasi perakitan perpustakaan yang lebih kompleks
komplikasi penyebaran perpustakaan
membuat perubahan, Anda perlu memasang kembali artefak untuk semua proyek
tidak ada kemungkinan beralih tema "dinamis". Akan sulit untuk menambahkan mode malam

Solusi


Selama seminggu kami mempelajari setiap opsi, mendiskusikan, menunda keputusan, dan mempelajari lagi.


Kami menyukai teknologi baru dan memantaunya, tetapi hanya menerapkannya jika memberi kami bonus nyata. Kami tahu tentang Variabel CSS, kami ingin mencobanya, tetapi kurangnya fungsi SCSS menyebabkan banyak kesedihan. Namun demikian, keuntungan dari opsi ini jelas, kami memutuskan untuk mencari tahu bagaimana dan apa fungsi SCSS yang kami gunakan, apakah mungkin untuk berteman dengan vars CSS.


Memahami CSS vs SCSS


Setelah bereksperimen, kami menyadari bahwa masalah utama adalah kurangnya dukungan untuk #hex di CSS: di SCSS kami menulis rgba(#ffffff, 0.4) , dan dalam CSS hal yang sama memerlukan serangkaian parameter yang berbeda - rgba(255, 255, 255, 0.4) . Semuanya bekerja untuk kita dengan #hex, dan kita benar-benar tidak ingin mengubah ini. Kami menemukan solusi, saya akan memberi tahu dalam urutan penerimaan.


Meringankan & menggelapkan


Desainer kami datang dengan palet yang terdiri dari sejumlah kecil warna dasar, berkembang karena fungsi SCSS untuk lighten dan darken :


 // $color –   base: $color, background: mix($color, #ffffff, 16%), backgroundHover: mix($color, #ffffff, 8%), hover: lighten($color, 5), focused: darken($color, 5), ...more transformations... 

Kami mencoba menemukan analog lighten dan darken dalam CSS, tetapi tidak menemukan apa pun. Kami berpikir selama beberapa hari sampai kami menyadari bahwa untuk penyesuaian kami perlu menyingkirkan fungsi-fungsi ini di dalam perpustakaan, mengeluarkannya. Bagaimanapun, setiap tim mungkin ingin membuat formula sendiri untuk mengubah warna saat mengubah fokus - misalnya, kolega dari Kids membutuhkan lebih banyak kontras.


Solusi sederhana adalah mentransfer transformasi kami ke sisi platform yang akan menginisialisasi topik. Dan untuk platform, kami menulis fungsi yang secara otomatis membuat nilai yang diperlukan:


 @function getMainColors($color, $colorText) { $colors: ( text: $colorText, base: $color, background: mix($color, #ffffff, 16%), backgroundHover: mix($color, #ffffff, 8%), lightenLess: lighten($color, 5), darkenLess: darken($color, 5), lightenMore: lighten($color, 20), ); @return $colors; } 

Platform menggunakannya saat menginisialisasi warna:


 //platform $colorValues: ( brand: getMainColors(#5d9cec, #4287df), positive: getMainColors(#8cc152, #55a900), accent: getMainColors(#ff3d6f, #ff255d), wrong: getMainColors(#ff6666, #fe4f44), ) 

RGBA


Dalam kit UI kami, kami menggunakan fungsi rgba . Dengan itu, kami menyesuaikan transparansi warna dasar. Tetapi jika rgba bekerja dengan #hex di SCSS, maka CSS tidak bisa. Saya harus menulis fungsi yang menguraikan nilai #hex menjadi r / g / b:


 // returns `r, g, b` from `#hex` for `rgba(var(--smth))` usage @function rgbValuesFromHex($hex) { @return red($hex), green($hex), blue($hex); } 

Ya, karena kami tidak ingin menghasilkan nilai RGB dengan pegangan ke seluruh palet, kami membuat fungsi terpisah yang melakukan ini secara rekursif untuk setiap warna dalam koleksi:


 // adds `fieldRgb: r, g, b` fields to map for each `field: #hex` for `rgba(var(--smth-rgb))` usage @function withRgbValues($map) { $rgbValues: (); @each $name, $value in $map { $formattedValue: (); @if type-of($value) == 'map' { $rgbValues: map-merge($rgbValues, (#{$name}: withRgbValues($value))); } @else { //   , rgb    Rgb   $rgbValues: map-merge($rgbValues, (#{$name}Rgb: rgbValuesFromHex($value))); } } @return map-merge($map, $rgbValues); } 

Akibatnya, inisialisasi palet dengan nilai-nilai RGB yang dihasilkan terlihat seperti ini:


 $colorValues: withRgbValues( ( text: ( base: #242d34, secondary: #50575c, label: #73797d, placeholder: #969b9e, inversed: #ffffff, inversedSecondary: #dadada, ), brand: getMainColors(#5d9cec, #4287df), positive: getMainColors(#8cc152, #55a900), accent: getMainColors(#ff3d6f, #ff255d), wrong: getMainColors(#ff6666, #fe4f44), //...etc 

Outputnya adalah peta warna SCSS, yang kemudian dapat diubah menjadi metode yang mengubahnya menjadi variabel CSS. Untuk mendapatkan nilai dari tema RGB, kami menulis sebuah fungsi:


 @function getUiKitRgbVar($path...) { $path: set-nth($path, -1, #{nth($path, -1)}Rgb); //       @return getFromMap($uiKitBaseVars, $path...); } //  border-color: rgba(getUiKitRgbVar(color, brand, base), $opacity64); 

Ubah SCSS const menjadi vars CSS


Langkah pertama adalah membuat struktur cermin (mirip dengan SCSS) yang menyimpan nama Variabel CSS:


 $colorCssVars: withRgbCssVars( ( text: ( base: getColorCssVar(text, base), secondary: getColorCssVar(text, secondary), label: getColorCssVar(text, label), placeholder: getColorCssVar(text, placeholder), inversed: getColorCssVar(text, inversed), //   

getColorCssVar - metode yang menambahkan awalan ke nama variabel. Tambahkan awalan --sky untuk menghindari tabrakan dengan perpustakaan eksternal. Dan juga menambahkan - UI kit perpustakaan awalan ke --sky untuk menghindari konflik dengan perpustakaan internal. Ternyata --sky- UI kit :


 @function getColorCssVar($parts...) { @return getUiKitCssVar(color, $parts...); } @function getUiKitCssVar($parts...) { $uiKitCssVarPrefix: '--sky- UI kit'; $cssVar: $uiKitCssVarPrefix; @each $part in $parts { $cssVar: $cssVar + '-' + $part; } @return $cssVar; } 

Sebagai contoh, untuk getColorCssVar(text, base) kita mendapatkan --sky- UI kit-color-text-base pada output.


Sentuhan terakhir adalah mixin rekursif yang menginisialisasi nilai dari struktur SCSS ke variabel dengan nama dari struktur Var CSS:


 //       :root { @include uiKitThemeCssVars($uiKitDefaultTheme); //uiKitDefaultTheme – SCSS       } @mixin uiKitThemeCssVars($theme) { $cssVarsList: createVarsList($theme, $uiKitBaseCssVars); //18+,    Map  List, $uiKitBaseCssVars   css  @each $cssVar, $value in $cssVarsList { #{$cssVar}: $value; } } 

Contoh menggunakan tema pada platform:


 .popup { font-family: getUiKitVar(font, family); background-color: getUiKitVar(color, background, base); ... } 

Apa hasilnya


Kami dapat menggunakan Variabel CSS, sambil mempertahankan kemampuan untuk menggunakan fungsi SCSS. Menciptakan kemampuan untuk menyesuaikan tampilan komponen. Kami menulis beberapa metode rekursif untuk mengotomatiskan perluasan topik. Nah dan yang paling penting - menghabiskan 30 jam pengembangan bukannya N * 500.


Untung!

Source: https://habr.com/ru/post/id459194/


All Articles