home | sitemap

CSS: Less en prefixer

Liever lui dan moe? Laat het cms je dan helpen met het werken met css:

CSS met variabelen, functies, etc...

Zou het niet makkelijk zijn als je in CSS variabelen kunt gebruiken? Bijvoorbeeld iets als

@kleur: black;

en verderop in de CSS:

#header h1 {
  color: @kleur;
}
...
div .item {
  background: @kleur url(/gfx/plaatje.gif) 0 0 no-repeat;
}

Of complete blokjes CSS vaker in te kunnen zetten, bijvoorbeeld

.bordered { 
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
}
...
#menu a { 
  color: #111; 
  .bordered;
} 

wat wordt omgezet in

#menu a { 
  color: #111;   
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
} 

LESS is more...

Met de 'taal' LESS is bovenstaande mogelijk. LESS is een uitbreiding op CSS, is backwards compatibel met CSS en de extra mogelijkheden maken gebruik van dezelfde syntax als CSS.

LESS activeren

Het cms zal LESS in een CSS bestand pas verwerken als dit expliciet wordt aangeven door onderstaande regel op te nemen in de CSS, bijvoorbeeld aan het begin van het bestand:

/* xcms: less */

Vervolgens kan gebruik worden gemaakt van LESS:

Variablen

Variabelen zijn recht-toe recht-aan:

LESS:   Uitkomst: 

@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;
#header {
  color: @light-blue;
}

  #header {
  color: #6c94be;

NB: variabelen zijn eigenlijk constanten die maar één keer gedefinieerd kunnen worden.

Mixins

In LESS is het mogelijk om een aantal regels samen te voegen en deze elders weer in te voegen:

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

Als we bovenstaande regels elders weer willen invoegen, dan voegen we gewoon de class name in:

LESS:    Uitkomst: 
.bordered { 
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
}
#menu a { 
  color: #111; 
  .bordered;
} 
.post a { 
  color: red; 
  .bordered;
}
 
.bordered { 
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
}
#menu a { 
  color: #111; 
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
} 
.post a { 
  color: red; 
  border-top: dotted 1px black; 
  border-bottom: solid 2px black;
}

NB: elke class name, id of element kan worden gebruik als naam voor de mixin. En de class name, id of element (.bordered zoals in het bovenstaande voorbeeld) kan natuurlijk ook gewoon worden gebruikt in de html (bijvoorbeeld: ... <a class="bordered"...>).

Mixins met parameters

Een mixin kan ook als een functie worden gebruikt zodat hij steeds weer kan worden hergebruikt met andere waarden:

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

Voor @radius kan nu steeds een andere waarde worden opgegeven:

LESS:   Uitkomst:
.border-radius (@radius) { 
  border-radius: @radius; 
  -moz-border-radius: @radius; 
  -webkit-border-radius: @radius;
}
#header { 
  .border-radius(4px);
} 
.button { 
  .border-radius(6px);
} 
 
#header { 
  border-radius: 4px; 
  -moz-border-radius: 4px; 
  -webkit-border-radius: 4px;
} 
.button { 
  border-radius: 6px; 
  -moz-border-radius: 6px; 
  -webkit-border-radius: 6px;
} 
 

Een mixin met parameters kan ook een default waarde hebben:

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

die we kunnen aanroepen met

#header { 
  .border-radius; 
}

waarmee #header een border-radius van 5px krijgt.

Je kunt ook een mixin met () maken en geen parameters opgeven. Dit kan handig zijn als je de regels zelf niet in de uiteindelijke CSS wilt laten opnemen:

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

Nested rules

LESS geeft je ook de mogelijkheid om CSS genest op te nemen. Stel je hebt de volgende CSS:

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

In LESS kunnen we dit als volgt opschrijven:

#header { 
  color: black; 
  .navigation { 
    font-size: 12px; 
  } 
  .logo { 
    width: 300px; 
    &:hover { 
      text-decoration: none; 
    } 
  } 
}

Het resultaat is dat de CSS overeenkomt met de structuur zoals in de HTML.

Let op de & combinator — die kan worden gebruikt om een geneste selector toe te voegen aan zijn parent. Dit is met name handig voor pseudo-classes als :hover en :focus.

Voorbeeld:

LESS:   Uitkomst:
.bordered { 
  &.float { 
    float: left; 
  } 
  .top { 
    margin: 5px; 
  }
}

a {
  text-decoration: none;
  color: red;
  &:hover {
    text-decoration: underline;
  }
}
 
.bordered.float { float: left; } 
.bordered .top [ margin: 5px;}

a {
  text-decoration: none;
  color: red;
}
a:hover {
  text-decoration: underline;
}

Berekeningen

Met elk getal, kleur of variabele kunnen berekeningen worden uitgevoerd. Enkele voorbeelden:

@base: 5%;
@base-color: #333; 
@filler: @base * 2; /* = 10% */
@other: @base + @filler; /* = 15% */
.item {
  color: #888 / 4; /* = #222 */
  background-color: @base-color + #111; /* = #444 */  
  height: 100% / 2 + @filler; /* = 60% */

}

De uitvoer is precies wat je er van verwacht — LESS kent het verschill tussen getallen en kleuren. Als een eenheid is opgegeven zal die ook worden gebruikt in de uitvoer:

@var: 1px + 5; 

LESS zal de eenheid px gebruiken voor de uitkomst — 6px in dit geval.

Haakjes zijn ook toegestaan:

width: (@var + 5) * 2;

Haakjes zijn verplicht bij een samengestelde regel:

border: (@width * 2) solid black;

Groeperen

Soms kan het handig zijn om variabelen en mixins te combineren. Bijvoorbeeld om duidelijk te maken dat ze bij elkaar horen maar je ze toch los wilt kunnen aanroepen:

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

Als we nu de .button uit #bundle ergens willen gebruiken, dan roepen we die als volgt aan:

LESS:   Uitkomst:
#header a { 
  color: orange; 
  #bundle > .button;
}
 
#header a { 
  color: orange; 
  display: block; 
  border: 1px solid black; 
  background-color: grey;
}
#header a:hover { 
  background-color: white;
}
 

Scope

Scope in LESS werkt net zoals in andere programmeertalen:

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

Escaping

Soms kan het nodig zijn dat een CSS waarde niet door LESS moet worden verwerkt, bijvoorbeeld omdat het geen (geldige) CSS is of iets is dat LESS niet herkent. In dat geval kun je de e() functie gebruiken die een string als parameter accepteerd:

.class { filter: e("progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png')"); }
#header {
  color: red;
  width: e("expression('10+12')");
}

Wat zal resulteren in:

.class { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png'); }
#header {
  color: red;
  width: expression('10+12');
}

CSS3 vendor prefixes (ook voor sommige CCS2 zaken!)

Nadeel van CSS3 is dat het (ten tijde van schrijven) nog geen standaard is en elke browser zo'n beetje zijn eigen prefixes nodig heeft. Volgens de standaard zou bijvoorbeeld

a {
  opacity: .5
  border-box-shadow: 20px;
  border-radius: 5px;
}
a:hover {
  transition: box-shadow 2s;
}

voldoende moeten zijn, maar om elke browser zijn zin te geven moet je

a {
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
  filter: alpha(opacity=50);
  opacity: .5;

  -webkit-box-shadow: 20px;
  -moz-box-shadow: 20px;
  box-shadow: 20px;

  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
a:hover {
  -webkit-transition: -webkit-box-shadow 2s;
  -moz-transition: -moz-box-shadow 2s;
  -o-transition: box-shadow 2s;
  -ms-transition: box-shadow 2s;
  transition: box-shadow 2s;
}

toepassen.

Dat schiet natuurlijk niet op, kost veel tijd, maakt de css code onoverzichtelijk, etc. Liever lui dan moe? laat het cms dan de nodige prefixes en andere browser oneffenheden gladstrijken door

/* xcms: prefix */

aan je css bestand toe te voegen, bijv. als eerste regel.