Less



less

Less

نظرة عامة

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

المتغيرات

هذه هي جميلة لا تحتاج إلى شرح:

@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;

#header {
  color: @light-blue;
}

المخرجات:

#header {
  color: #6c94be;
}

لاحظ أن المتغيرات هي في الواقع "ثوابت" في أنه لا يمكن تعريفها إلا مرة واحدة.

Mixins

المزيج هي طريقة لإدراج ("الاختلاط في") مجموعة من الخصائص من قاعدة واحدة إلى مجموعة قواعد أخرى. لنفترض أن لدينا الصف التالي:

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

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

#menu a {
  color: #111;
  .bordered;
}

.post a {
  color: red;
  .bordered;
}

.bordered خصائص الفئة .bordered الآن في #menu a و #menu a (لاحظ أنه يمكنك أيضًا استخدام #ids .)

أعرف أكثر

قواعد متداخلة

أقل يمنحك القدرة على استخدام التعشيش بدلاً من ، أو بالاشتراك مع المتتالية. لنفترض أن لدينا CSS التالي:

#header {
  color: black;
}
#header .navigation {
  font-size: 12px;
}
#header .logo {
  width: 300px;
}

في أقل ، يمكننا أيضا أن نكتب ذلك بهذه الطريقة:

#header {
  color: black;
  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
  }
}

الشفرة الناتجة أكثر اختصارًا ، وتحاكي بنية HTML.

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

.clearfix {
  display: block;
  zoom: 1;

  &:after {
    content: " ";
    display: block;
    font-size: 0;
    height: 0;
    clear: both;
    visibility: hidden;
  }
}

أنظر أيضا

التوجيهات المتداخلة والمراوغة

يمكن أن تتداخل التوجيهات مثل media أو keyframe بالطريقة نفسها مثل المحددات. يتم وضع التوجيه في الأعلى ويظل الترتيب النسبي ضد العناصر الأخرى داخل نفس المجموعة دون تغيير. هذا ما يسمى الفقاعة.

التوجيهات @Media مثل @Media و @supports و @document لها أيضًا محددات تم نسخها إلى أجسادهم:

.screen-color {
  @media screen {
    color: green;
    @media (min-width: 768px) {
      color: red;
    }
  }
  @media tv {
    color: black;
  }
}

المخرجات:

@media screen {
  .screen-color {
    color: green;
  }
}
@media screen and (min-width: 768px) {
  .screen-color {
    color: red;
  }
}
@media tv {
  .screen-color {
    color: black;
  }
}

هناك فقاعات غير مشروطة متبقية ، على سبيل المثال ، font-face keyframes أو keyframes ، تكون مغمورة أيضًا. أجسامهم لا تتغير:

#a {
  color: blue;
  @font-face {
    src: made-up-url;
  }
  padding: 2 2 2 2;
}

المخرجات:

#a {
  color: blue;
}
@font-face {
  src: made-up-url;
}
#a {
  padding: 2 2 2 2;
}

عمليات

العمليات الحسابية + ، - ، * ، / يمكن أن تعمل على أي رقم أو لون أو متغير. إذا أمكن ، تأخذ العمليات الحسابية الوحدات بعين الاعتبار وتحويل الأرقام قبل إضافة أو طرح أو مقارنة. تكون النتيجة في أقصى اليسار نوع وحدة صريح. إذا كان التحويل مستحيلاً أو غير ذي مغزى ، يتم تجاهل الوحدات. مثال للتحويل المستحيل: px to cm أو rad to٪.

// numbers are converted into the same units
@conversion-1: 5cm + 10mm; // result is 6cm
@conversion-2: 2 - 3cm - 5mm; // result is -1.5cm

// conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // result is 4px

// example with variables
@base: 5%;
@filler: @base * 2; // result is 10%
@other: @base + @filler; // result is 15%

لا يقوم الضرب والقسمة بتحويل الأرقام. لن يكون ذا معنى في معظم الحالات - الطول المضروب في الطول يعطي مساحة و css لا يدعم تحديد المناطق. أقل سيعمل على الأرقام كما هي وتعيين نوع وحدة صريح إلى النتيجة.

@base: 2cm * 3mm; // result is 6cm

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

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

عملية على الألوان تنتج دائما لون صالح. إذا انتهى الأمر ببعض أبعاد اللون للنتيجة لتصبح أكبر من ff أو أصغر من 00 ، فسيتم تقريب البُعد إلى إما ff أو 00 . إذا كانت قيمة alpha أكبر من 1.0 أو أصغر من 0.0 ، فسيتم تقريب ألفا إلى 1.0 أو 0.0 .

@color: #224488 / 2; //results in #112244
background-color: #112244 + #111; // result is #223355

الهروب

يتيح لك الهروب استخدام أي سلسلة عشوائية كممتلكات أو قيمة متغيرة. يتم استخدام أي شيء داخل ~"anything" أو ~'anything' كما هو الحال مع عدم وجود تغييرات باستثناء interpolation .

.weird-element {
  content: ~"^//* some horrible but needed css hack";
}

النتائج في:

.weird-element {
  content: ^//* some horrible but needed css hack;
}

المهام

أقل يوفر مجموعة متنوعة من الوظائف التي تحول الألوان ، وتتلاعب السلاسل والقيام الرياضيات. يتم توثيقها بشكل كامل في مرجع الدالة.

استخدامهم سهل جدا. يستخدم المثال التالي النسبة المئوية لتحويل 0.5 إلى 50٪ ، ويزيد تشبع اللون الأساسي بنسبة 5٪ ، ثم يقوم بتعيين لون الخلفية إلى اللون الذي يتم تخفيفه بنسبة 25٪ ونسج بمقدار 8 درجات:

@base: #f04615;
@width: 0.5;

.class {
  width: percentage(@width); // returns `50%`
  color: saturate(@base, 5%);
  background-color: spin(lighten(@base, 25%), 8);
}

مساحات الأسماء و Accessors

(يجب عدم الخلط بينه وبين @namespace أو محددات مساحة الاسم ).

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

#bundle {
  .button {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white
    }
  }
  .tab { ... }
  .citation { ... }
}

الآن إذا أردنا .button فئة .button في #header a بنا #header a ، يمكننا القيام به:

#header a {
  color: orange;
  #bundle > .button;
}

لاحظ أن المتغيرات المعلنة ضمن مساحة الاسم سيتم تحديد نطاقها إلى مساحة الاسم هذه فقط ولن تكون متاحة خارج النطاق عبر نفس البنية التي ستستخدمها للإشارة إلى mixin ( #Namespace > .mixin-name ). لذلك ، على سبيل المثال ، لا يمكنك القيام بما يلي: ( #Namespace > @this-will-not-work ).

نطاق

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

@var: red;

#page {
  @var: white;
  #header {
    color: @var; // white
  }
}

لا يجب أن يتم الإعلان عن المتغيرات والميول قبل استخدامها ، لذلك فإن الشفرة الأقل مماثلة مماثلة للمثال السابق:

@var: red;

#page {
  #header {
    color: @var; // white
  }
  @var: white;
}

أنظر أيضا

تعليقات

يمكن استخدام كل من التعليقات ذات النمط الشامل والمضمنة:

/* One hell of a block
style comment! */
@var: red;

// Get in line!
@var: white;

استيراد

استيراد يعمل إلى حد كبير كما هو متوقع. يمكنك استيراد ملف .less ، .less جميع المتغيرات فيه. تم تحديد الامتداد اختياريًا لملفات .less ملفات.

@import "library"; // library.less
@import "typo.css";

المتغيرات

السيطرة على القيم المستخدمة في مكان واحد.

نظرة عامة

ليس من غير الشائع أن ترى نفس القيمة تتكرر العشرات إن لم تكن مئات المرات عبر أوراق أنماطك:

a,
.link {
  color: #428bca;
}
.widget {
  color: #fff;
  background: #428bca;
}

تجعل المتغيرات من السهل الحفاظ على التعليمات البرمجية الخاصة بك من خلال منحك طريقة للتحكم في هذه القيم من موقع واحد:

// Variables
@link-color:        #428bca; // sea blue
@link-color-hover:  darken(@link-color, 10%);

// Usage
a,
.link {
  color: @link-color;
}
a:hover {
  color: @link-color-hover;
}
.widget {
  color: #fff;
  background: @link-color;
}

الاستيفاء المتغير

تركز الأمثلة الواردة أعلاه على استخدام المتغيرات للتحكم في القيم في قواعد CSS ، ولكن يمكن استخدامها أيضًا في أماكن أخرى أيضًا ، مثل أسماء المحددات وأسماء المواقع وعناوين URL وبيانات @import .

محددات

الإصدار: 1.4.0

// Variables
@my-selector: banner;

// Usage
[email protected]{my-selector} {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

يجمع إلى:

.banner {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

عناوين

// Variables
@images: "../img";

// Usage
body {
  color: #444;
  background: url("@{images}/white-sand.png");
}

بيانات الاستيراد

الإصدار: 1.4.0

التركيب: @import "@{themes}/tidal-wave.less";

لاحظ أنه قبل v2.0.0 ، تم النظر فقط في المتغيرات التي تم الإعلان عنها في الجذر أو النطاق الحالي وأنه تم النظر فقط في الملف الحالي وملفات الاتصال عند البحث عن متغير.

مثال:

// Variables
@themes: "../../src/themes";

// Usage
@import "@{themes}/tidal-wave.less";

الخصائص

الإصدار: 1.6.0

@property: color;

.widget {
  @{property}: #0ee;
  [email protected]{property}: #999;
}

يجمع إلى:

.widget {
  color: #0ee;
  background-color: #999;
}

أسماء متغيرة

من الممكن أيضًا تعريف المتغيرات باسم متغير:

@fnord:  "I am fnord.";
@var:    "fnord";
content: @@var;

الذي يجمع إلى:

content: "I am fnord.";

تقييم كسول

المتغيرات هي كسول تقييم وليس من الضروري أن يتم الإعلان عنها قبل استخدامها.

صالح مقتطف أقل:

.lazy-eval {
  width: @var;
}

@var: @a;
@a: 9%;

هذا صحيح أقل من ذلك:

.lazy-eval-scope {
  width: @var;
  @a: 9%;
}

@var: @a;
@a: 100%;

كلاهما تجميع في:

.lazy-eval-scope {
  width: 9%;
}

عند تحديد متغير مرتين ، يتم استخدام التعريف الأخير للمتغير ، بالبحث من النطاق الحالي لأعلى. يشبه هذا CSS نفسه حيث يتم استخدام الخاصية الأخيرة داخل تعريف لتحديد القيمة.

على سبيل المثال:

@var: 0;
.class {
  @var: 1;
  .brass {
    @var: 2;
    three: @var;
    @var: 3;
  }
  one: @var;
}

يجمع إلى:

.class {
  one: 1;
}
.class .brass {
  three: 3;
}

المتغيرات الافتراضية

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

على سبيل المثال:

// library
@base-color: green;
@dark-color: darken(@base-color, 10%);

// use of library
@import "library.less";
@base-color: red;

يعمل هذا بشكل جيد بسبب تجاوز التحميل الكامن - يتم استبدال اللون الأساسي باللون الداكن والأحمر الداكن.

تمديد

التمديد هو فئة زائفة أقل تقوم بدمج المحدد الذي يتم وضعه مع تلك التي تطابق ما تشير إليه.

صدر v1.4.0

nav ul {
  &:extend(.inline);
  background: blue;
}

في القاعدة المبينة أعلاه ، يقوم الخيار .inline selector بتطبيق " .inline selector" ( nav ul ) على فئة .inline أينما تظهر فئة .inline . سيتم الاحتفاظ بملف الإعلان كما هو ، ولكن بدون أي إشارة إلى الامتداد (لأن الامتداد ليس css).

لذلك ما يلي:

nav ul {
  &:extend(.inline);
  background: blue;
}
.inline {
  color: red;
}

المخرجات

nav ul {
  background: blue;
}
.inline,
nav ul {
  color: red;
}

لاحظ كيف أن nav ul:extend(.inline) selector يحصل على الإخراج مثل nav ul - تتم إزالة الامتداد قبل الإخراج ويترك كتلة المحدد كما هو. إذا لم يتم وضع أي خصائص في هذه المجموعة ، فستتم إزالتها من المخرجات (لكن الامتداد قد يؤثر على محددات أخرى).

تمديد بناء الجملة

يمتد الامتداد إلى محدد أو يوضع في مجموعة قواعد. يبدو وكأنه فئة زائفة مع معلمة selector متبوعة اختيارياً متبوعة بالكلمة الأساسية:

مثال:

.a:extend(.b) {}

// the above block does the same thing as the below block
.a {
  &:extend(.b);
}
.c:extend(.d all) {
  // extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
.c:extend(.d) {
  // extends only instances where the selector will be output as just ".d"
}

يمكن أن يحتوي على فئة واحدة أو أكثر للتمديد ، مفصولة بفواصل.

مثال:

.e:extend(.f) {}
.e:extend(.g) {}

// the above an the below do the same thing
.e:extend(.f, .g) {}

تمديد تعلق على محدد

يبدو أن التمديد المرفق إلى محدد يبدو كطبقة زائفة عادية مع محدد كمعلمة. يمكن أن يحتوي المحدد على العديد من جمل الامتداد ، ولكن يجب أن يكون كل الامتدادات في نهاية المحدد.

  • pre:hover:extend(div pre) بعد التحديد: pre:hover:extend(div pre) .
  • المساحة بين المحدد والتوسيع مسموح بها: pre:hover :extend(div pre) .
  • يُسمح pre:hover:extend(div pre):extend(.bucket tr) المتعدد: pre:hover:extend(div pre):extend(.bucket tr) - لاحظ أن هذا هو نفسه مثل pre:hover:extend(div pre, .bucket tr)
  • هذا غير مسموح به: pre:hover:extend(div pre).nth-child(odd) . يجب أن يكون التمديد الأخير.

إذا كانت مجموعة القواعد تحتوي على محددات متعددة ، يمكن لأي منها أن يمتلك الكلمة الأساسية الممتدة. محددات متعددة مع تمديد في مجموعة قواعد واحدة:

.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
  // body
}

تمديد داخل Ruleset

يمكن وضع &:extend(selector) في هيكل مجموعة القواعد باستخدام &:extend(selector) . يُعد وضع التمديد في الجسم اختصارًا لوضعه في كل مُحدد وحيد لهذه المجموعة.

التمدد داخل الجسم:

pre:hover,
.some-class {
  &:extend(div pre);
}

هو بالضبط نفس إضافة امتداد بعد كل محدد:

pre:hover:extend(div pre),
.some-class:extend(div pre) {}

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

توسيع قادر على مطابقة المحددات المتداخلة. بعد أقل:

مثال:

.bucket {
  tr { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(.bucket tr) {} // nested ruleset is recognized

المخرجات

.bucket tr,
.some-class {
  color: blue;
}

أساسا ينظر التمدد إلى المغلق المترجمة ، وليس الأصلي أقل.

مثال:

.bucket {
  tr & { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(tr .bucket) {} // nested ruleset is recognized

المخرجات

tr .bucket,
.some-class {
  color: blue;
}

المطابقة التامة مع تمديد

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

مثال:

.a.class,
.class.a,
.class > .a {
  color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above

النجم الرائد يهم. تكون المحددات *.class و .class ، ولكن الامتداد لن يتطابق معهما:

*.class {
  color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector

المخرجات

*.class {
  color: blue;
}

ترتيب الطبقات الزائفة لا يهم. link:hover:visited المحددات link:hover:visited link:visited:hover تطابق link:visited:hover مع مجموعة العناصر نفسها ، لكن توسيع نطاق التعامل معها يختلف عن بعضها:

link:hover:visited {
  color: blue;
}
.selector:extend(link:visited:hover) {}

المخرجات

link:hover:visited {
  color: blue;
}

nth التعبير

شكل تعبير nth لا يهم. تعبيرات 1n+3 و n+3 متكافئة ، لكن الامتداد لن يطابقها:

:nth-child(1n+3) {
  color: blue;
}
.child:extend(:nth-child(n+3)) {}

المخرجات

:nth-child(1n+3) {
  color: blue;
}

لا يهم نوع اقتباس في محدد السمة. كل ما يلي تعادل.

[title=identifier] {
  color: blue;
}
[title='identifier'] {
  color: blue;
}
[title="identifier"] {
  color: blue;
}

.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}

المخرجات

[title=identifier],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

تمديد "الكل"

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

مثال:

.a.b.test,
.test.c {
  color: orange;
}
.test {
  &:hover {
    color: green;
  }
}

.replacement:extend(.test all) {}

المخرجات

.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
  color: orange;
}
.test:hover,
.replacement:hover {
  color: green;
}

يمكنك التفكير في طريقة التشغيل هذه بشكل أساسي لإجراء بحث غير مدمر واستبداله.

انتقاء سائل مع تمديد

توسيع ليس قادراً على مطابقة محددات مع المتغيرات. إذا احتوى محدد على متغير ، فسوف يتجاهل الامتداد.

هناك طلب ميزة معلقة لهذا ولكن ليس تغييرًا سهلاً. ومع ذلك ، يمكن إرفاق تمديد إلى محدد interpolated.

لا يمكن مطابقة المحدد مع المتغير:

@variable: .bucket;
@{variable} { // interpolated selector
  color: blue;
}
.some-class:extend(.bucket) {} // does nothing, no match is found

والتوسع مع متغير في محدد الهدف لا يطابق أي شيء:

.bucket {
  color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket;

كل من الأمثلة السابقة تتجميع في:

.bucket {
  color: blue;
}

ومع ذلك ، :extend تعلق على أعمال محدد interpolated:

.bucket {
  color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;

السابقة أقل ترجمة إلى:

.bucket, .selector {
  color: blue;
}

Scoping / Extend Insidemedia

يجب أن يتطابق التمديد المكتوب داخل إعلان الوسائط مع محددات داخل نفس إعلام الوسائط:

@media print {
  .screenClass:extend(.selector) {} // extend inside media
  .selector { // this will be matched - it is in the same media
    color: black;
  }
}
.selector { // ruleset on top of style sheet - extend ignores it
  color: red;
}
@media screen {
  .selector {  // ruleset inside another media - extend ignores it
    color: blue;
  }
}

يجمع في:

@media print {
  .selector,
  .screenClass { /*  ruleset inside the same media was extended */
    color: black;
  }
}
.selector { /* ruleset on top of style sheet was ignored */
  color: red;
}
@media screen {
  .selector { /* ruleset inside another media was ignored */
    color: blue;
  }
}

لا يتطابق التمديد المكتوب داخل إعلام الوسائط مع المحددات الموجودة داخل تعريف متداخل:

@media screen {
  .screenClass:extend(.selector) {} // extend inside media
  @media (min-width: 1023px) {
    .selector {  // ruleset inside nested media - extend ignores it
      color: blue;
    }
  }
}

يجمع في:

@media screen and (min-width: 1023px) {
  .selector { /* ruleset inside another nested media was ignored */
    color: blue;
  }
}

يطابق المستوى العلوي كل شيء بما في ذلك المحددات الموجودة داخل الوسائط المتداخلة:

@media screen {
  .selector {  /* ruleset inside nested media - top level extend works */
    color: blue;
  }
  @media (min-width: 1023px) {
    .selector {  /* ruleset inside nested media - top level extend works */
      color: blue;
    }
  }
}

.topLevel:extend(.selector) {} /* top level extend matches everything */

يجمع في:

@media screen {
  .selector,
  .topLevel { /* ruleset inside media was extended */
    color: blue;
  }
}
@media screen and (min-width: 1023px) {
  .selector,
  .topLevel { /* ruleset inside nested media was extended */
    color: blue;
  }
}

اكتشاف الازدواجية

حاليا لا يوجد الكشف عن الازدواجية.

مثال:

.alert-info,
.widget {
  /* declarations */
}

.alert:extend(.alert-info, .widget) {}

المخرجات

.alert-info,
.widget,
.alert,
.alert {
  /* declarations */
}

استخدام الحالات لتوسيع

حالة الاستخدام الكلاسيكية

حالة الاستخدام الكلاسيكية هي تجنب إضافة فئة أساسية. على سبيل المثال ، إذا كان لديك

.animal {
  background-color: black;
  color: white;
}

وتريد أن يكون لديك نوع فرعي من الحيوان الذي يتجاوز لون الخلفية ثم لديك خيارين ، أولاً تغيير HTML الخاص بك

<a class="animal bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  background-color: brown;
}

أو يمكنك تبسيط html واستخدام التمديد في أقل. على سبيل المثال

<a class="bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}

تقليل حجم CSS

تنسخ ميكسينز جميع الخصائص إلى محدد ، مما قد يؤدي إلى تكرار غير ضروري. لذلك يمكنك استخدام الامتدادات بدلاً من المزيج لتحريك المحدد إلى الخصائص التي ترغب في استخدامها ، مما يؤدي إلى توليد css أقل.

مثال - مع mixin:

.my-inline-block() {
  display: inline-block;
  font-size: 0;
}
.thing1 {
  .my-inline-block;
}
.thing2 {
  .my-inline-block;
}

المخرجات

.thing1 {
  display: inline-block;
  font-size: 0;
}
.thing2 {
  display: inline-block;
  font-size: 0;
}

مثال (مع يمتد):

.my-inline-block {
  display: inline-block;
  font-size: 0;
}
.thing1 {
  &:extend(.my-inline-block);
}
.thing2 {
  &:extend(.my-inline-block);
}

المخرجات

.my-inline-block,
.thing1,
.thing2 {
  display: inline-block;
  font-size: 0;
}

الجمع بين أنماط / A أكثر تقدما Mixin

حالة استخدام أخرى هي كبديل للخلط - لأنه لا يمكن استخدام الاختلاط إلا مع محددات بسيطة ، إذا كان لديك كتلتان مختلفتان من html ، ولكنك تحتاج إلى تطبيق الأنماط نفسها على كلتا الطريقتين اللتين يمكنك استخدامهما لربط منطقتين.

مثال:

li.list > a {
  // list styles
}
button.list-style {
  &:extend(li.list > a); // use the same list styles
}

Mixins

خصائص "مزيج في" من الأنماط الموجودة

يمكنك مزج محددات الصف ومحددات الهوية ، على سبيل المثال

.a, #b {
  color: red;
}
.mixin-class {
  .a();
}
.mixin-id {
  #b();
}

مما يؤدي إلى:

.a, #b {
  color: red;
}
.mixin-class {
  color: red;
}
.mixin-id {
  color: red;
}

لاحظ أنه عند استدعاء mixin ، الأقواس اختيارية.

// these two statements do the same thing:
.a(); 
.a;

لا إخراج المزيج

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

.my-mixin {
  color: black;
}
.my-other-mixin() {
  background: white;
}
.class {
  .my-mixin;
  .my-other-mixin;
}

المخرجات

.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}

محددات في Mixins

يمكن أن تحتوي Mixins على أكثر من خصائص فقط ، يمكن أن تحتوي على محددات أيضًا.

فمثلا:

.my-hover-mixin() {
  &:hover {
    border: 1px solid red;
  }
}
button {
  .my-hover-mixin();
}

المخرجات

button:hover {
  border: 1px solid red;
}

مساحات

إذا كنت ترغب في دمج الخصائص داخل محدِّد أكثر تعقيدًا ، فيمكنك تجميع العديد من المعرفات أو الفئات.

#outer {
  .inner {
    color: red;
  }
}

.c {
  #outer > .inner;
}

ومرة أخرى كلاهما > و whitespace اختيارية

// all do the same thing
#outer > .inner;
#outer > .inner();
#outer .inner;
#outer .inner();
#outer.inner;
#outer.inner();

يُعرف استخدام واحد لهذا باسم namespacing. يمكنك وضع المزيج الخاص بك تحت محدد الهوية وهذا يضمن أنه لن يتعارض مع مكتبة أخرى.

مثال:

#my-library {
  .my-mixin() {
    color: black;
  }
}
// which can be used like this
.class {
  #my-library > .my-mixin();
}

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

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

#namespace when (@mode=huge) {
  .mixin() { /* */ }
}

#namespace {
  .mixin() when (@mode=huge) { /* */ }
}

يفترض أن الدالة default لها نفس القيمة لكافة مساحات الأسماء المتداخلة والخلط. لا يتم تقييم المزيج التالي من المزيج ، يتم ضمان أن يكون أحد حراسه غير صحيح:

#sp_1 when (default()) {
  #sp_2 when (default()) {
    .mixin() when not(default()) { /* */ }
  }
}

الكلمة الرئيسية !important

استخدم الكلمة الرئيسية !important بعد استدعاء mixin لوضع علامة على كل الخصائص الموروثة بها كـ !important :

مثال:

.foo (@bg: #f5f5f5, @color: #900) {
  background: @bg;
  color: @color;
}
.unimportant {
  .foo();
}
.important {
  .foo() !important;
}

النتائج في:

.unimportant {
  background: #f5f5f5;
  color: #900;
}
.important {
  background: #f5f5f5 !important;
  color: #900 !important;
}

ميكسات بارامترية

كيفية تمرير الحجج إلى mixins

يمكن أيضًا أن تتناول المزيج الحجج ، وهي متغيرات تمر إلى كتلة المحددات عندما يتم خلطها.

فمثلا:

.border-radius(@radius) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

وإليك الطريقة التي يمكننا بها مزجها في مجموعات القواعد المختلفة:

#header {
  .border-radius(4px);
}
.button {
  .border-radius(6px);
}

يمكن أيضًا أن تشتمل الاختلافات البارامترية على قيم افتراضية لمعلماتها:

.border-radius(@radius: 5px) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

يمكننا الاحتجاج بها على هذا النحو الآن:

#header {
  .border-radius;
}

وسوف تشمل دائرة نصف قطرها 5 بكسل.

يمكنك أيضا استخدام mixetric parametric التي لا تأخذ المعلمات. يكون هذا مفيدًا إذا كنت تريد إخفاء مجموعة القواعد من خلاصة CSS ، ولكنك تريد تضمين خصائصها في rulesets أخرى:

.wrap() {
  text-wrap: wrap;
  white-space: -moz-pre-wrap;
  white-space: pre-wrap;
  word-wrap: break-word;
}

pre { .wrap }

التي من شأنها إخراج:

pre {
  text-wrap: wrap;
  white-space: -moz-pre-wrap;
  white-space: pre-wrap;
  word-wrap: break-word;
}

Mixins مع معلمات متعددة

تكون المعلمات إما منقوطة أو مفصولة بفواصل . من المستحسن استخدام الفاصلة المنقوطة . يحتوي رمز الفاصلة على معنى مزدوج: يمكن تفسيره إما على هيئة فاصل معلمات mixin أو فاصل قائمة css.

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

  • وسيطتين يحتوي كل منهما على قائمة مفصولة بفواصل: .name(1, 2, 3; something, else) ،
  • ثلاث حجج وكل منها يحتوي على رقم واحد: .name(1, 2, 3) ،
  • استخدام فاصلة منقوطة نموذجية لإنشاء استدعاء mixin مع وسيطة واحدة تحتوي على قائمة css مفصولة بفواصل: .name(1, 2, 3;) ،
  • قيمة افتراضية مفصولة بفاصلة: .name(@param1: red, blue;) .

من القانوني تحديد عدة خلطات بنفس الاسم وعدد من المعلمات. أقل سوف تستخدم خصائص كل ما يمكن تطبيقه. إذا استخدمت .mixin(green); مع معلمة واحدة على سبيل المثال .mixin(green); ، ثم سيتم استخدام خصائص جميع mixins مع معلمة إلزامية واحدة بالضبط:

.mixin(@color) {
  color-1: @color;
}
.mixin(@color; @padding: 2) {
  color-2: @color;
  padding-2: @padding;
}
.mixin(@color; @padding; @margin: 2) {
  color-3: @color;
  padding-3: @padding;
  margin: @margin @margin @margin @margin;
}
.some .selector div {
  .mixin(#008000);
}

يجمع في:

.some .selector div {
  color-1: #008000;
  color-2: #008000;
  padding-2: 2;
}

المعلمات المسماة

يمكن لمرجع mixin توفير قيم المعلمات بأسمائها بدلاً من المواضع فقط. يمكن الإشارة إلى أي معلمة باسمها ولا يلزم أن تكون بأي ترتيب خاص:

.mixin(@color: black; @margin: 10px; @padding: 20px) {
  color: @color;
  margin: @margin;
  padding: @padding;
}
.class1 {
  .mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
  .mixin(#efca44; @padding: 40px);
}

يجمع في:

.class1 {
  color: #33acfe;
  margin: 20px;
  padding: 20px;
}
.class2 {
  color: #efca44;
  margin: 10px;
  padding: 40px;
}

@arguments المتغير

@arguments له معنى خاص داخل mixins ، أنه يحتوي على جميع الحجج التي تم تمريرها ، عندما تم استدعاء mixin. هذا مفيد إذا كنت لا ترغب في التعامل مع المعلمات الفردية:

.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
  -webkit-box-shadow: @arguments;
     -moz-box-shadow: @arguments;
          box-shadow: @arguments;
}
.big-block {
  .box-shadow(2px; 5px);
}

مما يؤدي إلى:

.big-block {
  -webkit-box-shadow: 2px 5px 1px #000;
     -moz-box-shadow: 2px 5px 1px #000;
          box-shadow: 2px 5px 1px #000;
}

الحجج المتقدمة و @rest المتغير

يمكنك استخدام ... إذا كنت تريد أن يأخذ mixin عددًا متغيرًا من الوسيطات. باستخدام هذا بعد اسم متغير سيتم تعيين هذه الوسيطات للمتغير.

.mixin(...) {        // matches 0-N arguments
.mixin() {           // matches exactly 0 arguments
.mixin(@a: 1) {      // matches 0-1 arguments
.mixin(@a: 1; ...) { // matches 0-N arguments
.mixin(@a; ...) {    // matches 1-N arguments

علاوة على ذلك:

.mixin(@a; @rest...) {
   // @rest is bound to arguments after @a
   // @arguments is bound to all arguments
}

نمط مطابقة

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

.mixin(@s; @color) { ... }

.class {
  .mixin(@switch; #888);
}

الآن دعنا نقول أننا نريد .mixin أن نتصرف بشكل مختلف ، بناءً على قيمة @switch ، يمكننا تحديد .mixin على هذا النحو:

.mixin(dark; @color) {
  color: darken(@color, 10%);
}
.mixin(light; @color) {
  color: lighten(@color, 10%);
}
.mixin(@_; @color) {
  display: block;
}

الآن ، إذا أجرينا:

@switch: light;

.class {
  .mixin(@switch; #888);
}

سنحصل على CSS التالي:

.class {
  color: #a2a2a2;
  display: block;
}

حيث تم تمرير اللون إلى .mixin . إذا كانت قيمة @switch dark ، فستكون النتيجة لونًا أكثر قتامة.

إليك ما حدث:

  • لم يتطابق تعريف mixin الأول لأنه يتوقع dark كوسيطة الأولى.
  • تطابق تعريف mixin الثاني ، لأنه يتوقع light .
  • تطابق تعريف mixin الثالث لأنه يتوقع أي قيمة.

تم استخدام تعريفات mixin فقط المتطابقة. المتغيرات تطابق وترتبط بأي قيمة. أي شيء آخر غير متغير يتطابق فقط مع قيمة مساوية لنفسها.

يمكننا أيضًا التطابق مع المعنويات ، وهنا مثال على ذلك:

.mixin(@a) {
  color: @a;
}
.mixin(@a; @b) {
  color: fade(@a; @b);
}

الآن إذا .mixin مع حجة واحدة ، سوف نحصل على ناتج التعريف الأول ، ولكن إذا أطلقنا عليه حجتين ، فسوف نحصل على التعريف الثاني ، وهو @a تلاشى إلى @b .

Mixins كوظائف

متغيرات العودة أو خلطات من mixins

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

مثال:

.mixin() {
  @width:  100%;
  @height: 200px;
}

.caller {
  .mixin();
  width:  @width;
  height: @height;
}

النتائج في:

.caller {
  width:  100%;
  height: 200px;
}

وبالتالي يمكن للمتغيرات المحددة في mixin بمثابة قيم الإرجاع الخاصة به. هذا يسمح لنا بإنشاء مزيج يمكن استخدامه كوظيفة تقريبًا.

مثال:

.average(@x, @y) {
  @average: ((@x + @y) / 2);
}

div {
  .average(16px, 50px); // "call" the mixin
  padding: @average;    // use its "return" value
}

النتائج في:

div {
  padding: 33px;
}

لا يمكن تجاوز المتغيرات المعرفة مباشرة في نطاق المتصلين. ومع ذلك ، لا يتم حماية المتغيرات المحددة في النطاق الرئيسي للمتصلين وسيتم تجاوزها:

.mixin() {
  @size: in-mixin;
  @definedOnlyInMixin: in-mixin;
}

.class {
  margin: @size @definedOnlyInMixin;
  .mixin();
}

@size: globaly-defined-value; // callers parent scope - no protection

النتائج في:

.class {
  margin: in-mixin in-mixin;
}

وأخيرًا ، يعمل المزيج المحدد في mixin كقيمة إرجاع أيضًا:

.unlock(@value) { // outer mixin
  .doSomething() { // nested mixin
    declaration: @value;
  }
}

#namespace {
  .unlock(5); // unlock doSomething mixin
  .doSomething(); //nested mixin was copied here and is usable
}

النتائج في:

#namespace {
  declaration: 5;
}

تمرير Rulesets إلى Mixins

السماح بتغليف كتلة CSS ، المحددة في mixin

صدر v1.4.0

مجموعة القواعد المنفصلة هي مجموعة من خصائص css أو rulesets المتداخلة أو إعلانات الوسائط أو أي شيء آخر مخزّن في متغير. يمكنك تضمينه في مجموعة قواعد أو هيكل آخر وسيتم نسخ جميع خصائصه هناك. يمكنك أيضًا استخدامه كوسيطة mixin وتمريره كمتغير آخر.

مثال بسيط:

// declare detached ruleset
@detached-ruleset: { background: red; };

// use detached ruleset
.top {
    @detached-ruleset(); 
}

يجمع في:

.top {
  background: red;
}

الأقواس بعد استدعاء مجموعة منفصلة هي إلزامية. الدعوة @detached-ruleset; لن يعمل.

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

.desktop-and-old-ie(@rules) {
  @media screen and (min-width: 1200px) { @rules(); }
  html.lt-ie9 &                         { @rules(); }
}

header {
  background-color: blue;

  .desktop-and-old-ie({
    background-color: red;
  });
}

هنا يعرّف mix desktop-and-old-ie mixin الاستعلام عن الوسائط وفئة الجذر بحيث يمكنك استخدام mixin لتغليف جزء من التعليمات البرمجية. هذا سوف يخرج

header {
  background-color: blue;
}
@media screen and (min-width: 1200px) {
  header {
    background-color: red;
  }
}
html.lt-ie9 header {
  background-color: red;
}

يمكن تعيين مجموعة القواعد الآن إلى متغير أو تمريرها إلى mixin ويمكن أن تحتوي على مجموعة كاملة من الميزات الأقل ، على سبيل المثال

@my-ruleset: {
    .my-selector {
      background-color: black;
    }
  };

يمكنك حتى الاستفادة من فقاعات الاستعلام عن الوسائط ، على سبيل المثال

@my-ruleset: {
    .my-selector {
      @media tv {
        background-color: black;
      }
    }
  };
@media (orientation:portrait) {
    @my-ruleset();
}

والتي سوف تخرج

@media (orientation: portrait) and tv {
  .my-selector {
    background-color: black;
  }
}

A detached ruleset call unlocks (returns) all its mixins into caller the same way as mixin calls do. However, it does NOT return variables.

Returned mixin:

// detached ruleset with a mixin
@detached-ruleset: { 
    .mixin() {
        color:blue;
    }
};
// call detached ruleset
.caller {
    @detached-ruleset(); 
    .mixin();
}

Results in:

.caller {
  color: blue;
}

Private variables:

@detached-ruleset: { 
    @color:blue; // this variable is private
};
.caller {
    color: @color; // syntax error
}

Scoping

A detached ruleset can use all variables and mixins accessible where it is defined and where it is called . Otherwise said, both definition and caller scopes are available to it. If both scopes contains the same variable or mixin, declaration scope value takes precedence.

Declaration scope is the one where detached ruleset body is defined. Copying a detached ruleset from one variable into another cannot modify its scope. The ruleset does not gain access to new scopes just by being referenced there.

Lastly, a detached ruleset can gain access to scope by being unlocked (imported) into it.

Definition and Caller Scope Visibility

A detached ruleset sees the caller's variables and mixins:

@detached-ruleset: {
  caller-variable: @caller-variable; // variable is undefined here
  .caller-mixin(); // mixin is undefined here
};

selector {
  // use detached ruleset
  @detached-ruleset(); 

  // define variable and mixin needed inside the detached ruleset
  @caller-variable: value;
  .caller-mixin() {
    variable: declaration;
  }
}

compiles into:

selector {
  caller-variable: value;
  variable: declaration;
}

Variable and mixins accessible form definition win over those available in the caller:

@variable: global;
@detached-ruleset: {
  // will use global variable, because it is accessible
  // from detached-ruleset definition
  variable: @variable; 
};

selector {
  @detached-ruleset();
  @variable: value; // variable defined in caller - will be ignored
}

compiles into:

selector {
  variable: global;
}

Referencing Won't Modify Detached Ruleset Scope

A ruleset does not gain access to new scopes just by being referenced there:

@detached-1: { scope-detached: @one @two; };
.one {
  @one: visible;
  .two {
    @detached-2: @detached-1; // copying/renaming ruleset 
    @two: visible; // ruleset can not see this variable
  }
}

.use-place {
  .one > .two(); 
  @detached-2();
}

throws an error:

ERROR 1:32 The variable "@one" was not declared.

Unlocking Will Modify Detached Ruleset Scope

A detached ruleset gains access by being unlocked (imported) inside a scope:

#space {
  .importer-1() {
    @detached: { scope-detached: @variable; }; // define detached ruleset
  }
}

.importer-2() {
  @variable: value; // unlocked detached ruleset CAN see this variable
  #space > .importer-1(); // unlock/import detached ruleset
}

.use-place {
  .importer-2(); // unlock/import detached ruleset second time
   @detached();
}

compiles into:

.use-place {
  scope-detached: value;
}

Import Directives

Import styles from other style sheets

In standard CSS, @import at-rules must precede all other types of rules. But Less.js doesn't care where you put @import statements.

مثال:

.foo {
  background: #900;
}
@import "this-is-valid.less";

File Extensions

@import statements may be treated differently by Less depending on the file extension:

  • If the file has a .css extension it will be treated as CSS and the @import statement left as-is (see the inline option below).
  • If it has any other extension it will be treated as Less and imported.
  • If it does not have an extension, .less will be appended and it will be included as a imported Less file.

أمثلة:

@import "foo";      // foo.less is imported
@import "foo.less"; // foo.less is imported
@import "foo.php";  // foo.php imported as a less file
@import "foo.css";  // statement left in place, as-is

The following options can be used to override this behavior.

Import Options

Less offers several extensions to the CSS @import CSS at-rule to provide more flexibility over what you can do with external files.

Syntax: @import (keyword) "filename";

The following import directives have been implemented:

  • reference : use a Less file but do not output it
  • inline : include the source file in the output but do not process it
  • less : treat the file as a Less file, no matter what the file extension
  • css : treat the file as a CSS file, no matter what the file extension
  • once : only include the file once (this is default behavior)
  • multiple : include the file multiple times
  • optional : continue compiling when file is not found

More than one keyword per @import is allowed, you will have to use commas to separate the keywords:

Example: @import (optional, reference) "foo.less";

reference

Use @import (reference) to import external files, but without adding the imported styles to the compiled output unless referenced.

Released v1.4.0

Example: @import (reference) "foo.less";

Imagine that reference marks every directive and selector with a reference flag in the imported file, imports as normal, but when the CSS is generated, "reference" selectors (as well as any media queries containing only reference selectors) are not output. reference styles will not show up in your generated CSS unless the reference styles are used as mixins or extended .

Additionally, reference produces different results depending on which method was used (mixin or extend):

  • extended : When a selector is extended, only the new selector is marked as not referenced , and it is pulled in at the position of the reference @import statement.
  • mixins : When a reference style is used as an implicit mixin , its rules are mixed-in, marked "not reference", and appear in the referenced place as normal.

reference example

This allows you to pull in only specific, targeted styles from a library such as Bootstrap by doing something like this:

.navbar:extend(.navbar all) {}

And you will pull in only .navbar related styles from Bootstrap.

inline

Use @import (inline) to include external files, but not process them.

Released v1.4.0

Example: @import (inline) "not-less-compatible.css";

You will use this when a CSS file may not be Less compatible; this is because although Less supports most known standards CSS, it does not support comments in some places and does not support all known CSS hacks without modifying the CSS.

So you can use this to include the file in the output so that all CSS will be in one file.

less

Use @import (less) to treat imported files as Less, regardless of file extension.

Released v1.4.0

مثال:

@import (less) "foo.css";

css

Use @import (css) to treat imported files as regular CSS, regardless of file extension. This means the import statement will be left as it is.

Released v1.4.0

مثال:

@import (css) "foo.less";

outputs

@import "foo.less";

once

The default behavior of @import statements. It means the file is imported only once and subsequent import statements for that file will be ignored.

Released v1.4.0

This is the default behavior of @import statements.

مثال:

@import (once) "foo.less";
@import (once) "foo.less"; // this statement will be ignored

multiple

Use @import (multiple) to allow importing of multiple files with the same name. This is the opposite behavior to once.

Released v1.4.0

مثال:

// file: foo.less
.a {
  color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";

Outputs

.a {
  color: green;
}
.a {
  color: green;
}

اختياري

Use @import (optional) to allow importing of a file only when it exists. Without the optional keyword Less throws a FileError and stops compiling when importing a file that can not be found.

Released v1.4.0

Mixin Guards

Conditional mixins

Guards are useful when you want to match on expressions , as opposed to simple values or arity. If you are familiar with functional programming, you have probably encountered them already.

In trying to stay as close as possible to the declarative nature of CSS, Less has opted to implement conditional execution via guarded mixins instead of if / else statements, in the vein of @media query feature specifications.

Let's start with an example:

.mixin (@a) when (lightness(@a) >= 50%) {
  background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
  background-color: white;
}
.mixin (@a) {
  color: @a;
}

The key is the when keyword, which introduces a guard sequence (here with only one guard). Now if we run the following code:

.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }

Here's what we'll get:

.class1 {
  background-color: black;
  color: #ddd;
}
.class2 {
  background-color: white;
  color: #555;
}

Guard Comparison Operators

The full list of comparison operators usable in guards are: > , >= , = , =< , < . Additionally, the keyword true is the only truthy value, making these two mixins equivalent:

.truth (@a) when (@a) { ... }
.truth (@a) when (@a = true) { ... }

Any value other than the keyword true is falsy:

.class {
  .truth(40); // Will not match any of the above definitions.
}

Note that you can also compare arguments with each other, or with non-arguments:

@media: mobile;

.mixin (@a) when (@media = mobile) { ... }
.mixin (@a) when (@media = desktop) { ... }

.max (@a; @b) when (@a > @b) { width: @a }
.max (@a; @b) when (@a < @b) { width: @b }

Guard Logical Operators

You can use logical operators with guards. The syntax is based on CSS media queries.

Use the and keyword to combine guards:

.mixin (@a) when (isnumber(@a)) and (@a > 0) { ... }

You can emulate the or operator by separating guards with a comma , . If any of the guards evaluate to true, it's considered a match:

.mixin (@a) when (@a > 10), (@a < -10) { ... }

Use the not keyword to negate conditions:

.mixin (@b) when not (@b > 0) { ... }

Type Checking Functions

Lastly, if you want to match mixins based on value type, you can use the is functions:

.mixin (@a; @b: 0) when (isnumber(@b)) { ... }
.mixin (@a; @b: black) when (iscolor(@b)) { ... }

Here are the basic type checking functions:

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl

If you want to check if a value is in a specific unit in addition to being a number, you may use one of:

  • ispixel
  • ispercentage
  • isem
  • isunit

Conditional Mixins

( FIXME ) Additionally, the default function may be used to make a mixin match depending on other mixing matches, and you may use it to create "conditional mixins" similar to else or default statements (of if and case structures respectively):

.mixin (@a) when (@a > 0) { ...  }
.mixin (@a) when (default()) { ... } // matches only if first mixin does not, i.e. when @a <= 0

CSS Guards

"if"'s around selectors

Released v1.4.0

Guards can also be applied to css selectors, which is syntactic sugar for declaring the mixin and then calling it immediately.

For instance, before 1.5.0 you would have had to do this:

.my-optional-style() when (@my-option = true) {
  button {
    color: white;
  }
}
.my-optional-style();

Now, you can apply the guard directly to a style.

button when (@my-option = true) {
  color: white;
}

You can also achieve an if type statement by combining this with the & feature, allowing you to group multiple guards.

& when (@my-option = true) {
  button {
    color: white;
  }
  a {
    color: blue;
  }
}

Loops

Creating loops

In Less a mixin can call itself. Such recursive mixins, when combined with Guard Expressions and Pattern Matching , can be used to create various iterative/loop structures.

مثال:

.loop(@counter) when (@counter > 0) {
  .loop((@counter - 1));    // next iteration
  width: (10px * @counter); // code for each iteration
}

div {
  .loop(5); // launch the loop
}

انتاج:

div {
  width: 10px;
  width: 20px;
  width: 30px;
  width: 40px;
  width: 50px;
}

A generic example of using a recursive loop to generate CSS grid classes:

.generate-columns(4);

.generate-columns(@n, @i: 1) when (@i =< @n) {
  [email protected]{i} {
    width: (@i * 100% / @n);
  }
  .generate-columns(@n, (@i + 1));
}

انتاج:

.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}

Merge

Combine properties

The merge feature allows for aggregating values from multiple properties into a comma or space separated list under a single property. merge is useful for properties such as background and transform.

Comma

Append property value with comma

Released v1.4.0

مثال:

.mixin() {
  box-shadow+: inset 0 0 10px #555;
}
.myclass {
  .mixin();
  box-shadow+: 0 0 20px black;
}

Outputs

.myclass {
  box-shadow: inset 0 0 10px #555, 0 0 20px black;
}

Space

Append property value with space

Released v1.4.0

مثال:

.mixin() {
  transform+_: scale(2);
}
.myclass {
  .mixin();
  transform+_: rotate(15deg);
}

Outputs

.myclass {
  transform: scale(2) rotate(15deg);
}

To avoid any unintentional joins, merge requires an explicit + or +_ flag on each join pending declaration.

Parent Selectors

Referencing parent selectors with &

The & operator represents the parent selectors of a nested rule and is most commonly used when applying a modifying class or pseudo-class to an existing selector:

a {
  color: blue;
  &:hover {
    color: green;
  }
}

results in:

a {
  color: blue;
}

a:hover {
  color: green;
}

Notice that without the & , the above example would result in a :hover rule (a descendant selector that matches hovered elements inside of <a> tags) and this is not what we typically would want with the nested :hover .

The "parent selectors" operator has a variety of uses. Basically any time you need the selectors of the nested rules to be combined in other ways than the default. For example another typical use of the & is to produce repetitive class names:

.button {
  &-ok {
    background-image: url("ok.png");
  }
  &-cancel {
    background-image: url("cancel.png");
  }

  &-custom {
    background-image: url("custom.png");
  }
}

output:

.button-ok {
  background-image: url("ok.png");
}
.button-cancel {
  background-image: url("cancel.png");
}
.button-custom {
  background-image: url("custom.png");
}

Multiple &

& may appear more than once within a selector. This makes it possible to repeatedly refer to a parent selector without repeating its name.

.link {
  & + & {
    color: red;
  }

  & & {
    color: green;
  }

  && {
    color: blue;
  }

  &, &ish {
    color: cyan;
  }
}

will output:

.link + .link {
  color: red;
}
.link .link {
  color: green;
}
.link.link {
  color: blue;
}
.link, .linkish {
  color: cyan;
}

Note that & represents all parent selectors (not just the nearest ancestor) so the following example:

.grand {
  .parent {
    & > & {
      color: red;
    }

    & & {
      color: green;
    }

    && {
      color: blue;
    }

    &, &ish {
      color: cyan;
    }
  }
}

results in:

.grand .parent > .grand .parent {
  color: red;
}
.grand .parent .grand .parent {
  color: green;
}
.grand .parent.grand .parent {
  color: blue;
}
.grand .parent,
.grand .parentish {
  color: cyan;
}

Changing Selector Order

It can be useful to prepend a selector to the inherited (parent) selectors. This can be done by putting the & after current selector. For example, when using Modernizr, you might want to specify different rules based on supported features:

.header {
  .menu {
    border-radius: 5px;
    .no-borderradius & {
      background-image: url('images/button-background.png');
    }
  }
}

The selector .no-borderradius & will prepend .no-borderradius to its parent .header .menu to form the .no-borderradius .header .menu on output:

.header .menu {
  border-radius: 5px;
}
.no-borderradius .header .menu {
  background-image: url('images/button-background.png');
}

Combinatorial Explosion

& can also be used to generate every possible permutation of selectors in a comma separated list:

p, a, ul, li {
  border-top: 2px dotted #366;
  & + & {
    border-top: 0;
  }
}

This expands to all possible (16) combinations of the specified elements:

p,
a,
ul,
li {
  border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
  border-top: 0;
}

原文