حول تعارضات Sass وميزات CSS الجديدة نسبيًا

في الآونة الأخيرة ، كان هناك العديد من الميزات المثيرة للاهتمام في CSS ، مثل CSS Variables والميزات الجديدة . في حين أن كل هذا يمكن أن يجعل الحياة أسهل كثيرًا لمصممي الويب ، إلا أن هذه الميزات يمكن أن تتفاعل مع معالجات CSS الأولية مثل Sass بطرق غير متوقعة. مؤلفة المادة ، التي ننشر ترجمتها اليوم ، ستتحدث عن المشاكل التي كان عليها مواجهتها ، وكيف تعاملت معها ، ولماذا تعتقد أن ساس لا يزال من المستحيل الاستغناء عنها.











أخطاء



إذا كنت تجريب مع CSS-ميزات min()و max()ثم استخدام وحدات قياس مختلفة، ونحن يمكن أن تواجه رسائل خطأ مثل هذا: Incompatible units: vh and em.





ظهور رسالة خطأ عند استخدام وحدات مختلفة في وظائف min () و max () تظهر



هذه الرسالة لأن Sass لها وظيفتها الخاصةmin().min()نتيجة لذلك ،يتمتجاهلوظيفة CSS. بالإضافة إلى ذلك ، لا يمكن لـ Sass إجراء العمليات الحسابية باستخدام الوحدات التي ليس لها علاقة واضحة بينها.



على سبيل المثال ، العلاقة بين الوحداتمحددةcmجيدًاin، لذا يمكن لـ Sass العثور على نتيجة دالةmin(20in, 50cm)ولا يخطئ إذا استخدمت شيئًا كهذا في التعليمات البرمجية الخاصة بك.



يحدث الشيء نفسه مع وحدات القياس الأخرى. على سبيل المثال ، جميع وحدات الزوايا مترابطة:1turn،1radأو1gradيتم تحويلها دائمًا إلى نفس القيم المعبر عنها بوحدات deg. وينطبق الشيء نفسه ، على سبيل المثال ، في حالة 1sتساوي دائمًا 1000ms. 1kHzيساوي دائما 1000Hz، 1dppxيساوي دائما 96dpi، 1inيساوي دائما 96px. هذا هو السبب في أن Sass يمكنها تحويل القيم المعبر عنها في هذه الوحدات إلى بعضها البعض ، ومزجها في الحسابات المستخدمة في وظائف مختلفة ، مثل وظيفتها الخاصة min().



لكن كل شيء يحدث بشكل خاطئ عندما لا توجد علاقة واضحة بين وحدات القياس (على سبيل المثال ، أعلاه ، ص emو vh).



وهذا لا يحدث فقط عند استخدام القيم المعبر عنها بوحدات قياس مختلفة. تحاول استخدام وظيفة calc()داخلياmin()يؤدي أيضًا إلى حدوث خطأ. إذا حاولت min()، ووضع شيء من هذا القبيل calc(20em + 7px)، فإنه يعرض هذا الخطأ: calc(20em + 7px) is not a number for min.





تظهر رسالة الخطأ عندما تحاول استخدام calc () في دقيقة ()



تحدث مشكلة أخرى في الموقف عند محاولة استخدام متغير CSS أو إخراج وظائف CSS الرياضية (مثلcalc()،min()،max()) في عوامل تصفية تشبه CSSinvert().



إليك رسالة الخطأ التي قد تراها في ظل ظروف مماثلة:$color: 'var(--p, 0.85) is not a color for invert





باستخدام فار () في فلتر: عكس () النتائج في خطأ



ويحدث الشيء نفسه معgrayscale():$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.





باستخدام احسب () في فلتر: الرمادي () النتائج في خطأ



تصميمfilter: opacity()تخضع أيضا إلى قضايا مماثلة:$color: ‘var(--p, 0.8)‘ is not a color for opacity.





باستخدام فار () في فلتر: غموض () النتائج في خطأ



، ولكن الوظائف الأخرى المستخدمةfilter، بما في ذلكsepia()،blur()،drop-shadow()،brightness()،contrast()وhue-rotate()، والعمل مع المتغيرات-CSS أمر طبيعي تماما!



اتضح أن سبب هذه المشكلة مشابه للذي يؤثر على وظائفmin()وmax(). Sass ليست وظائف مضمنةsepia()،blur()،drop-shadow()،brightness()،contrast()،hue-rotate(). لكنه لا يملك وظائفها الخاصة درجات الرمادي () ، قلب () و التعتيم () . الوسيطة الأولى لهذه الوظائف هي القيمة$color. يظهر الخطأ بسبب حقيقة أنه عند استخدام الإنشاءات الإشكالية ، لا يجد Sass مثل هذه الحجة.



للسبب نفسه ، تظهر المشكلات عند استخدام متغيرات CSS التي تمثل قيمتين hsl()أو hsla()قيمتين على الأقل .





خطأ عند استخدام var () في اللون: hsl ()



من ناحية أخرى ، بدون استخدام Sass ، يكون البناءcolor: hsl(9, var(--sl, 95%, 65%))صحيحًا تمامًا ويعمل بشكل مثالي في CSS.



وينطبق الشيء نفسه على وظائف مثلrgb()وrgba():





خطأ في استخدام var () في اللون: rgba ()



أيضًا ، إذا قمت باستيراد Compass وحاولت استخدام متغير CSS في الداخل،linear-gradient()أوradial-gradient()قد تواجه خطأ آخر. لكن في نفس الوقت ،conic-gradient()يمكنك استخدام المتغيرات دون أي مشاكل (بالطبع ، إذا كان المتصفح يدعم هذه الوظيفة).





الخطي التدرج (): خطأ باستخدام فار () في الخلفية



والسبب في هذه المشكلة يكمن في حقيقة أن البوصلة لديها قناعاتها الخطية التدرج () وradial-gradient()ظائف، ولكن وظيفةconic-gradient()لم يكن أبدا هناك.



بشكل عام ، كل هذه المشاكل تنبع من حقيقة أن Sass أو Compass لهما وظائف خاصة بهما ، وأسماؤها هي نفسها الموجودة في CSS. يعتقد كل من Sass و Compass ، عند تلبية هذه الوظائف ، أننا سنستخدم تطبيقاتهم الخاصة لهذه الوظائف ، وليس تلك القياسية.



هنا كمين!



المحلول



يمكن حل هذه المشكلة من خلال تذكر أن Sass حساس لحالة الأحرف ، لكن CSS ليس كذلك.



هذا يعني أنه يمكنك كتابة شيء مثل هذا Min(20em, 50vh)ولا يتعرف Sass على وظيفته في هذا البناء min(). لن يتم إنشاء أي أخطاء. سيكون هذا البناء عبارة عن CSS جيد التكوين يعمل تمامًا كما هو متوقع. وبالمثل ، فإن التخلص من مشاكل الوظائف الأخرى يمكن أن يكون ، بطريقة غير قياسية عن طريق كتابة أسمائها: HSL()، HSLA()، RGB()، RGBA()، ، Invert().



عندما يتعلق الأمر بالتدرجات ، عادةً ما أستخدم هذا الشكل: linear-Gradient()و radial-Gradient(). أفعل هذا لأن هذا الترميز قريب من الأسماء المستخدمة في SVG، ولكن في هذه الحالة ، سيعمل أي اسم مشابه يتضمن حرفًا كبيرًا واحدًا على الأقل.



لماذا كل هذه التعقيدات؟



تقريبًا في كل مرة أغرد فيها شيئًا عن Sass ، تلقيت محاضرات حول كيف أصبح لديك الآن متغيرات CSS ، فأنت لست بحاجة إلى استخدام Sass بعد الآن. قررت أنني يجب أن أجيب على هذا وأشرح سبب اختلافي مع هذه الفكرة.



أولاً ، سألاحظ أنني أجد متغيرات CSS مفيدة للغاية ، وأنني استخدمتها في مجموعة متنوعة من المهام على مدار السنوات الثلاث الماضية. لكنني أفترض أنك بحاجة إلى أن تضع في اعتبارك أن استخدامها له تأثير على الأداء. والبحث عن مشكلة في متاهة المكالماتcalc()يمكن أن تكون أكثر التجارب غير السارة. أدوات مطور المستعرض القياسية ليست جيدة جدًا في هذا الأمر حتى الآن. أحاول عدم الانجراف في استخدام متغيرات CSS ، حتى لا أدخل في مواقف تظهر فيها عيوبها نفسها أكثر من مزاياها.





ليس من السهل فهم نتائج تقييم تعبيرات calc () هذه



، بشكل عام ، إذا تم استخدام متغير باعتباره ثابتًا ، فإنه لا يتغير من عنصر إلى عنصر ، أو من حالة إلى حالة (وفي مثل هذه الحالات ، يجب أن تستخدم متغيرات CSS بالتأكيد مطلوب ) ، أو إذا كان المتغير لا يقلل من كمية CSS المترجمة (حل مشكلة التكرار التي تم إنشاؤها بواسطة البادئات) ، فسأستخدم متغير Sass.



ثانيًا ، كان الدعم المتغير دائمًا سببًا بسيطًا جدًا من بين أسباب استخدامي لـ Sass. عندما بدأت باستخدام Sass في النصف الثاني من عام 2012 ، قمت بذلك بشكل أساسي من أجل الحلقات. لميزة لا تزال تفتقر إليها CSS. على الرغم من أنني قمت بنقل بعض منطق التكرار الحلقي إلى معالج HTML الأولي (نظرًا لأن هذا يقلل من مقدار التعليمات البرمجية التي تم إنشاؤها ويتجنب الحاجة إلى تعديل كل من HTML و CSS) ، ما زلت أستخدم حلقات Sass في كثير من الحالات. يتضمن ذلك إنشاء قوائم من القيم ، وإنشاء قيم لضبط التدرجات ، وإنشاء قوائم بالنقاط عند العمل باستخدام دالة polygon()، وإنشاء قوائم بالتحويلات ، وما إلى ذلك.



يوجد أدناه مثال لما كنت سأفعله سابقًا عند إنشاء بعض عناصر HTML باستخدام المعالج المسبق. أي معالج لا يهم حقًا ، لكنني اخترت Pug:



- let n = 12;

while n--
  .item


ثم أقوم بإنشاء متغير $nفي Sass (ويجب أن يكون لهذا المتغير نفس القيمة الموجودة في HTML) وأبدأ حلقة باستخدامه ، حيث يمكنني إنشاء التحويلات المستخدمة لوضع كل عنصر من العناصر:



$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}' }
    }
  }
}


الجانب السلبي لهذا هو أنني سأضطر إلى تغيير القيم في كل من كود Pug ورمز Sass في حالة تغيير عدد العناصر. بالإضافة إلى ذلك ، هناك الكثير من التكرار في الكود.





تم إنشاء CSS من الكود أعلاه



الآن اتخذت نهجًا مختلفًا. وبالتحديد ، باستخدام Pug ، أقوم بإنشاء الفهارس كخصائص مخصصة ثم استخدمها في الإعلانtransform.



إليك الكود الذي يخطط Pug لمعالجته:



- let n = 12;

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


هذا هو كود ساس:



$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) }
}


يمكنك تجربة هذا الرمز هنا.





العناصر التي تم



إنشاؤها وتصميمها باستخدام الحلقات Loops أدى استخدام هذا الأسلوب إلى تقليل كمية CSS التي تم إنشاؤها تلقائيًا بشكل كبير.





تم إنشاء CSS من الكود أعلاه



ولكن إذا كنت تريد إنشاء شيء مثل قوس قزح ، فلا يمكنك الاستغناء عن حلقات Sass.



@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()) }


إليك نسخة عمل من هذا المثال.





خلفية متعددة الألوان



بالطبع ، يمكن إنشاء ذلك باستخدام متغيرات Pug ، لكن هذا النهج لا يتمتع بميزة على الطبيعة الديناميكية لمتغيرات CSS ، ولن يقلل من كمية الشفرة التي يتم إرسالها إلى المتصفح. نتيجة لذلك ، ليس من المنطقي بالنسبة لي أن أتخلى عما اعتدت عليه.



أنا أستخدم وظائف الرياضيات المضمنة في Sass (والبوصلة) كثيرًا ، مثل الدوال المثلثية. في هذه الأيام ، تعد هذه الميزات جزءًا من مواصفات CSS ، ولكن ليست كل المتصفحات تدعمها بعد. ليس لدى Sass هذه الوظائف ، لكن Compass لها هذه الوظائف ، ولهذا أجد نفسي غالبًا أستخدم Compass.



وبالطبع يمكنني كتابة الوظائف الخاصة بي من هذا النوع في Sass. لقد فعلت ذلك في البداية ، قبل أن تدعم البوصلة الدوال المثلثية العكسية. أحتاج حقًا إلى هذه الوظائف ، لذلك قمت بكتابتها بنفسي باستخدام سلسلة تايلور . لكن في هذه الأيام البوصلة لها تلك الوظائف. هم أفضل وأكثر إنتاجية من أولئك الذين كتبتهم بنفسي.



وظائف الرياضيات مهمة جدًا بالنسبة لي لأنني مبرمج ولست فنانًا. عادةً ما يتم إنشاء القيم الموجودة في كود CSS الخاص بي من الحسابات الرياضية. هذه ليست بعض "الأرقام السحرية" ، أو شيئًا يلعب دورًا جماليًا بحتًا. مثال على استخدامها هو إنشاء قائمة من المضلعات العادية أو شبه العادية لـclip-path... يستخدم هذا ، على سبيل المثال ، عند إنشاء شيء مثل الصور الرمزية أو الملصقات ، والتي يختلف شكلها عن المستطيل.



خذ بعين الاعتبار مضلعًا منتظمًا تقع رءوسه على دائرة. يتيح لنا سحب شريط التمرير في المثال التالي ، والذي يمكننا تجربته هنا ، معرفة مكان وضع النقاط للأشكال ذات الأرقام المختلفة للرؤوس.





شكل بثلاثة رؤوس



وهذا ما يبدو عليه كود 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 
}


يرجى ملاحظة أننا نستخدم الحلقات والتركيبات الأخرى هنا ، وهي غير ملائمة للاستخدام مع CSS النقي.



قد يتضمن الإصدار الأكثر تقدمًا من هذا المثال تدوير المضلع بإضافة نفس الإزاحة ( $oa) إلى الزاوية المقابلة لكل رأس. يمكن ملاحظة ذلك في المثال التالي . يتم إنشاء النجوم هنا ، والتي يتم ترتيبها بطريقة مماثلة ، ولكن دائمًا ما يكون لها عدد زوجي من الرؤوس. علاوة على ذلك ، يقع كل رأس بمؤشر فردي على دائرة نصف قطرها أقل من الدائرة الرئيسية ( $f*50%).





نجمة



يمكنك عمل مثل هذه النجوم المثيرة للاهتمام.





النجوم



يمكنك إنشاء ملصقات بحدود (border) تم إنشاؤها باستخدام قوالب غير معتادة. في هذا المثال ، يتم إنشاء الملصق من عنصر HTML واحد ، ويتم إنشاء القالب المستخدم للتخصيصborderباستخدامclip-pathحلقات Sass والرياضيات. في الواقع ، هناك الكثير من الحسابات هنا.





ملصقات بحدود معقدة مثال



آخرهو كيفية إنشاء خلفية للبطاقات. هنا ، في حلقة ، باستخدام عامل المعامل والوظائف الأسية ، يتم إنشاء خلفية بتقليد تأثير التردد.





تأثير التردد



هنا أيضًا ، يتم استخدام متغيرات CSS بكثرة.بعد



ذلك ، يمكنك التفكير في استخدام mixins لتجنب الاضطرار إلى كتابة نفس الإعلان مرارًا وتكرارًا عند تصميم شيء مثل أشرطة التمرير . تستخدم المتصفحات المختلفة عناصر زائفة مختلفة لتصميم المكونات الداخلية لعناصر التحكم هذه ، لذلك تحتاج إلى تحديد أنماط لكل مكون تتحكم في مظهرها باستخدام عناصر زائفة مختلفة.



لسوء الحظ ، في CSS ، كما يبدو مغرًا ، لا يمكنك وضع شيء مثل الكود التالي:



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


لن تنجح. يتم تجاهل هذه المجموعة الكاملة من القواعد إذا لم يتم التعرف على محدد واحد على الأقل. ونظرًا لأنه لا يوجد متصفح على دراية بوجود المحددات الثلاثة في هذا المثال ، فلن يتم تطبيق هذه الأنماط في أي متصفح.



إذا كنت تريد أن يعمل التصميم ، فستحتاج إلى القيام بشيء مثل هذا:



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


ولكن هذا يمكن أن يتسبب في ظهور نفس الأنماط ثلاث مرات في الكود. وإذا كنت في حاجة، مثلا، لتغيير trackالملكية background، وهذا يعني أن لديك لتحرير الأنماط في ::-webkit-slider-runnable-track، في ::-moz-range-trackو ::-ms-track.



الحل العاقل الوحيد لهذه المشكلة هو استخدام mixins. تتكرر الأنماط في الكود المترجم ، حيث لا توجد طريقة للاستغناء عنها ، لكننا الآن ، على الأقل ، لا يتعين علينا إدخال نفس الرمز ثلاث مرات في المحرر.



@mixin track() { /*   */ }

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


النتيجة



الاستنتاج الرئيسي الذي يمكنني استخلاصه هو: Sass in شيء لا يمكننا الاستغناء عنه.



هل تستخدم Sass؟






All Articles