CSS: دليل دالة calc () الكامل

يحتوي CSS على وظيفة خاصة calc()تُستخدم لإجراء العمليات الحسابية البسيطة. هنا مثال على استخدامه:

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

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





دالة Calc () وقيم خصائص CSS


المكان الوحيد الذي يمكنك استخدام الوظيفة فيه calc()هو قيم خاصية CSS. ألق نظرة على الأمثلة التالية ، باستخدام هذه الوظيفة ، نعين قيم الخصائص المختلفة.

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

calc()يمكن أيضًا استخدام الوظيفة لتعيين أي جزء منفصل من الخاصية:

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

قد تكون هذه الوظيفة جزءًا من وظيفة أخرى مسؤولة عن تكوين جزء من خاصية معينة! على سبيل المثال ، هنا يتم calc()استخدامه لضبط موضع تغير لون التدرج:

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

الدالة calc () هي أداة للعمل بخصائص رقمية.


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

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

هناك العديد من وحدات القياس التي يمكن استخدامها في CSS لتحديد حجم العناصر وأجزائها: px، %، em، rem، in، mm، cm، pt، pc، ex، ch، vh، vw، vmin، vmax. يمكن استخدام كل هذه الوحدات مع الوظيفة calc().

يمكن أن تعمل هذه الوظيفة أيضًا مع الأرقام المستخدمة بدون تحديد الوحدات:

line-height: calc(1.2 * 1.2);

يمكن استخدامه أيضًا لحساب الزوايا:

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

يمكن استخدام هذه الوظيفة أيضًا في تلك الحالات عندما لا يتم إجراء الحسابات في التعبير الذي يتم تمريره إليها:

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

لا يمكن استخدام Calc () في استعلامات الوسائط


على الرغم من أن هذه الوظيفة مصممة لتعيين قيم خاصية CSS ، فإنها للأسف لا تعمل في استعلامات الوسائط:

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

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

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

استخدام وحدات مختلفة في تعبير واحد


ربما تكون مقبولية استخدام وحدات قياس مختلفة في تعبير واحد هي الفرصة الأكثر قيمة calc(). يستخدم مماثل في كل الأمثلة المذكورة أعلاه تقريبًا. هنا ، فقط لفت انتباهك إليه ، مثال آخر يوضح استخدام وحدات قياس مختلفة:

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

يقرأ هذا التعبير كما يلي: "العرض يساوي عرض العنصر الذي يتم طرح 20 بكسل منه."

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

في ما يلي مثالان إضافيان لاستخدام القيم المعبر عنها بوحدات مختلفة:

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

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

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

مقارنة calc () مع حسابات المعالج الأولي


قلنا للتو أن الميزة الأكثر فائدة calc()ليست قابلة للمعالجة المسبقة. لكن المعالجة المسبقة تمنح المطور بعض الميزات التي تتوافق مع القدرات calc(). على سبيل المثال ، عند استخدام Sass ، يمكنك أيضًا حساب قيم الخصائص:

$padding: 1rem;

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

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

الكشف عن معنى القيم الرقمية المستخدمة في CSS


حتى إذا لم تستغل الفرص التي لا يمكن تحقيقها إلا بمساعدة calc()، يمكن استخدام هذه الوظيفة للكشف عن معنى القيم المستخدمة في CSS. افترض أنك تريد أن تكون قيمة الخاصية 1/7 بالضبط من عرض العنصر:

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

  /*   */
  width: 14.2857142857%;
}

قد يكون هذا النهج مفيدًا في شيء يشبه نوعًا من CSS-API المصمم ذاتيًا:

[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); }

العمليات الحسابية للدالة الحسابية ()


التعبير التي سيتم تقييمها مع مساعدة من calc()المشغلين يمكنك استخدامها +، -، *و /. ولكن في تطبيقهم هناك بعض الميزات.

عند إضافة ( +) وطرح ( -) ، يجب عليك استخدام القيم مع الوحدات المحددة

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

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

يرجى ملاحظة أن استخدام القيم غير الصحيحة يؤدي إلى حقيقة أن إعلانًا معينًا يصبح أيضًا غير صحيح.

عند القسمة ( /) ، من الضروري عدم الإشارة إلى وحدة القياس على الرقم الثاني

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

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

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

عند ضرب ( *) ، يجب ألا يحتوي أحد الأرقام على وحدة قياس:

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

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

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

أهمية المساحات


تعتبر المسافات المستخدمة في التعبيرات مهمة في عمليات الجمع والطرح:

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

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

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

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

هنا من الممكن جدًا استخدام الأرقام السالبة (على سبيل المثال ، في بناء مثل calc(5vw — -5px)) ، ولكن هذا مثال على حالة لا تكون فيها المساحات ضرورية فحسب ، ولكنها مفيدة أيضًا من حيث وضوح التعبيرات.

أخبرني Tab Atkins أن سبب فصل عوامل الجمع والطرح بمسافات هو في الواقع خصوصيات تعبيرات التحليل. لا أستطيع أن أقول إنني فهمت هذا تمامًا ، ولكن على سبيل المثال ، يعالج المحلل التعبير 2px-3pxكعدد 2مع وحدة قياسpx-3px. ولن يحتاج أحد إلى وحدة قياس غريبة. تحليل التعبيرات مع عامل الجمع له مشاكله الخاصة. على سبيل المثال ، يمكن للمحلل أن يأخذ هذا العامل كجزء من بناء الجملة المستخدم لوصف الأرقام. اعتقدت أن هناك حاجة إلى مساحة للتعامل مع بنية الخصائص المخصصة ( --) بشكل صحيح ، ولكن هذا ليس هو الحال.

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

المسافات التي تفصل الأقواس calc()عن التعبير لا تلعب أي دور. يمكن تحديد التعبير ، إذا رغبت في ذلك ، بالانتقال إلى سطر جديد:

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

صحيح ، يجب أن تكون حذرا هنا. calcيجب ألا تكون هناك مسافات بين اسم الوظيفة ( ) وقوس الفتح الأول:

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

الإنشاءات المتداخلة: calc (calc ())


عند العمل مع وظيفة calc()، يمكنك استخدام الإنشاءات المتداخلة ، ولكن هذا ليس ضروريًا حقًا. هذا مشابه لاستخدام الأقواس بدون calc:

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

ليس من المنطقي بناء الإنشاءات المتداخلة من الوظائف calc()، حيث يمكن إعادة كتابة نفس باستخدام الأقواس فقط:

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

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

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

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

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

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

خصائص CSS المخصصة وحساب ()


لقد تعلمنا بالفعل عن إحدى الميزات الرائعة calc()، عن الحسابات التي تستخدم القيم مع وحدات مختلفة. ميزة أخرى مثيرة للاهتمام لهذه الوظيفة هي كيف يمكن تطبيقها مع خصائص CSS المخصصة. يمكن تعيين الخصائص المخصصة للقيم التي يمكن استخدامها في العمليات الحسابية:

html {
  --spacing: 10px;
}

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

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

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

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

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

بالنسبة للبعض قد لا يبدو هذا ملائمًا للغاية ، لأنه عند الوصول إلى خاصية مخصصة ، تحتاج إلى تذكرها calc(). لكني أجد هذا مثيرًا للاهتمام من حيث سهولة قراءة التعليمات البرمجية.

يمكن أن يكون مصدر الخصائص المخصصة هو كود HTML. في بعض الأحيان يمكن أن يكون هذا مفيدًا للغاية. على سبيل المثال ، في Splitting.js تتم إضافة الفهارس إلى الكلمات والرموز.

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

تعيين الوحدات إلى الخصائص المخصصة بعد إعلان هذه الخصائص


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

html {
  --importantNumber: 2;
}

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

العمل مع الزهور


عند وصف الألوان باستخدام تنسيقات مثل RGB و HSL ، يتم استخدام الأرقام. يمكن العمل على هذه الأرقام calc(). على سبيل المثال ، يمكنك تعيين بعض قيم HSL الأساسية ، ثم تغييرها حسب الحاجة ( هنا مثال):

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

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

لا يمكنك الجمع بين calc () و attr ()


attr()يمكن أن تبدو وظيفة CSS جذابة للغاية. والحقيقة: تأخذ قيمة السمة من HTML ، ثم تستخدمها. لكن…

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

لسوء الحظ ، لا تفهم هذه الوظيفة "أنواع" القيم. ونتيجة لذلك ، فهي attr()مناسبة فقط للعمل مع السلاسل وتعيين خصائص CSS باستخدامها content. وهذا يعني أن مثل هذا التصميم يعمل بشكل جيد:

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

قلت هذا هنا لأن شخصًا ما قد يرغب في محاولة استخراج attr()رقم معين من كود HTML واستخدامه في الحسابات:

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

ومع ذلك ، فإن الشيء الجيد هو أنه لا يهم حقًا ، لأن الخصائص المخصصة في HTML رائعة لحل مثل هذه المشاكل:

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

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

أدوات المتصفح


تعرض أدوات مطور المتصفح عادةً التعبيرات calc()بنفس الطريقة الموضحة في شفرة مصدر CSS.


أدوات المطور في Firefox ، علامة التبويب القواعد

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


علامة التبويب المحسوبة في أدوات مطوري Chrome

دعم المتصفح


هنا يمكنك معرفة المزيد عن دعم calc()المتصفح لهذه الميزة . إذا تحدثنا عن المتصفحات الحديثة ، فإن مستوى الدعم calc()يزيد عن 97٪. إذا كنت بحاجة إلى دعم المتصفحات القديمة إلى حد ما (مثل IE 8 أو Firefox 3.6) ، فعادة ما يقومون بذلك: أضف calc()نفس الخاصية قبل الخاصية لحساب القيمة التي تم تعيينها بتنسيق يفهمه المتصفحات القديمة:

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

تحتوي الوظيفة calc()على العديد من المشاكل المعروفة ، ولكن المتصفحات القديمة فقط تعاني منها. على Caniuse يمكن العثور على وصف 13 من هذه المشاكل. هنا بعض منهم:

  • متصفح فايرفوكس أدناه الإصدار 59 لا يدعم calc()الوظائف المستخدمة لتعيين اللون. على سبيل المثال: color: hsl(calc(60 * 2), 100%, 50%).
  • لن يقوم IE 9-11 بتقديم الظل المحدد بواسطة الخاصية box-shadowإذا تم استخدامه لتحديد أي من القيم calc().
  • لا يدعم IE 9-11 ولا Edge تصميم طريقة العرض width: calc()عند تطبيقها على خلايا الجدول.

أمثلة على الحياة


سألت العديد من مطوري CSS عن آخر مرة استخدموا فيها الوظيفة calc(). كانت إجاباتهم مجموعة صغيرة ستساعد الجميع على معرفة كيفية استخدام المبرمجين الآخرين calc()في عملهم اليومي.

  • أنا استخدم calc()لإنشاء فئة المساعد للحقول الإدارة: .full-bleed { width: 100vw; margin-left: calc(50% — 50vw); }. يمكنني القول أنه calc()في أفضل 3 ميزات مفيدة لـ CSS.
  • لقد استخدمت هذه الوظيفة لتخصيص مساحة لـ "تذييل" ثابت للصفحة.
  • calc() . , font-size, . font-sizecalc() 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.
  • أتقدم بطلب calc()للتحايل على القيود background-position. هذا ينطبق بشكل خاص على القيود على تعديل مواضع تغيير اللون في التدرجات. على سبيل المثال ، يمكن وصف ذلك على النحو التالي: "ضع موضع تغيير اللون ، وليس الوصول 0.75emإلى الأسفل".



القراء الأعزاء! هل تستخدم CSS calc()؟

All Articles