woensdag 10 juli 2013

Less - Dynamic Stylesheets in ASP.NET MVC 5

Een paar weken geleden is de eerste preview van Visual Studio 2013 uitgekomen. Over een aantal verbeteringen heb ik in mijn vorige blog al geschreven. In deze preview kunnen we ook kennis maken met ASP.NET MVC 5. Deze versie ondersteunt een aantal handige tools, zoals Twitter Bootstrap, SignalR, CoffeeScript en Less. Over Less wil ik het in deze blog hebben.
Al tijden gebruiken webontwikkelaars Cascading StyleSheets (css) voor het uiterlijk van webpagina's. Je hebt html dat aangeeft wat er op de pagina komt te staan en css dat verantwoordelijk is hoe de inhoud van de pagina eruit komt te zien. Hierbij moet je denken aan kleuren, lettertypes, afmetingen en allerlei gelikte effecten. Het grote nadeel van css is dat het vrij statisch is. In de praktijk resulteert dat in veel dubbele code. Natuurlijk kan een handig css-schrijver veel van deze problemen omzeilen, maar helaas is niet iedereen een ster in css. Met Less kunnen je als het ware css programmeren. Hieronder een voorbeeld dat het nut van Less duidelijk maakt.

.style1
{
    background-color:#7F34D3;
}

.style2
{
    color:#7F34D3;
}

.style3
{
    border: 0.2rem solid #7F34D3;
}

Natuurlijk is dit een nogal absurd voorbeeld, maar het komt vaak voor dat kleurcodes her en der in stylesheets opduiken. Ga die later dan maar eens aanpassen. Bovendien zegt #7F34D3 natuurlijk helemaal niets.
Met Less zou hetzelfde script er als volgt uitzien.

@paars#7F34D3;

.style1
{
    background-color:@paars;
}

.style2
{
    color:@paars;
}

.style3
{
    border: 0.2rem solid @paars;
}

Het eerste dat opvalt, is het statement @paars. Dit is in Less een variabele. Achter de ":" staat dan de waarde van die variabele. Merk op dat de variabele @paars nu overal gebruikt kan worden hetgeen de leesbaarheid en het hergebruik aanzienlijk bevordert.

Natuurlijk begrijpt een browser helemaal niets van dat gebrabbel. Vandaar dat er een compiler aanwezig moet zijn die dit alles vertaalt naar echt css. Deze compiler heb je in twee varianten: Een JavaScript versie voor de client en eentje voor op de server. Om de serverversie te gebruiken, moeten we eerst een compiler downloaden. Dat kan het eenvoudigst via nuget. De benodigde compiler voor .NET heet dotless. Nuget zal ook de benodigde referenties (dotless.Core) leggen en de web.config in orde maken. Hieronder zie je de wijzigingen die nuget maakt (andere zaken zijn eruit gelaten).

<configuration>
  <configSections>
    <section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler, dotless.Core" />
  </configSections>
  <system.web>
    <httpHandlers>
      <add path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler, dotless.Core" />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <handlers>
      <add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="" />
    </handlers>
  </system.webServer>
  <dotless minifyCss="false" cache="true" web="false" 
               handleWebCompression="false" />
</configuration>

Belangrijk hierbij zijn de httpHandlers waarbij de extensie .less wordt gekoppeld aan de compiler. Wanneer er een request met een .less extensie binnenkomt, zal het .less-bestand gecompileerd worden en het resultaat (puur css) wordt naar de client gestuurd. Bij het dotless element kun je verder nog aangeven of het script gecomprimeerd en/of gecached moet worden. Het attribuut handleWebCompression is nodig omdat het anders niet werkt in Visual Studio 2013.

De infrastructuur is nu in orde. Tijd om Less te gebruiken. Aan het webproject voegen we een "LESS Style Sheet" toe via het contextmenu "Add New Item" (afbeelding 1).


Afbeelding 1. Een Less bestand toevoegen.
Laten we eens het eerdere Less-script in een webpagina hangen. Dit gaat op dezelfde manier als bij normale css-bestanden, alleen verwijs je nu naar het .less-bestand.


<link href="~/Content/test.less" rel="stylesheet" />

In afbeelding 2 is het resultaat te zien.


Afbeelding 2. Less in action.
Een ander krachtig concept in Less is Mixings. Mixings kun je het best vergelijken met functies. Het is een verzameling css-eigenschappen die je in andere css-definities aanroept. 

@paars : #7F34D3;

.style1
{
    color:@paars;
}

.style2 (@radius, @color: @paars)
{
    border.2rem solid @color;
    border-radius@radius
}

.style3
{
    .style1;
    .style2(10%);
    opacity:.5;
}
.style1 en .style2 zijn functies (mixins). In .style2 zie je ook het gebruik van parameters (@radius en @color), met @color een optionele parameter. In .style3 worden .style1 en .style2 aangeroepen. Het uiteindelijke resultaat hiervan is hieronder weergegeven.


.style1
{
    background-color#7f34d3;
}

.style2
{
    color#7f34d3;
}

.style3
{
    color#7f34d3;
    border0.2rem solid #7f34d3;
    border-radius10%;
    opacity.5;
}
Less beschikt ook over een aantal operatoren, zoals "+", "-", "*" en "/". Daarbij wordt eventueel gepeuter met eenheden uit handen genomen. Hieronder zie je een aantal voorbeelden.

@screen_width400px;
@box_height@screen_width/4;
@green:#0f0;
@red:#f00;

#container
{
    height@box_height;
}

    #container .small
    {
        float:left;
        min-width: (@screen_width/4);
        background-color:@green;
    }

    #container .medium
    {
        float:left;
        min-width: (2 * (@screen_width/4));
        background-color:@red;
    }

Wanneer dit script door de less-compiler wordt getrokken, leidt dat tot het volgende css:

#container {
  height100px;
}
#container .small {
  floatleft;
  min-width100px;
  background-colorlime;
}
#container .medium {
  floatleft;
  min-width200px;
  background-colorred;
}

In Less heb je de beschikking over guards. Guards kun je zien als condities, zoals je die ook in if/else instructies tegenkomt. Hiervoor wordt het speciale sleutelwoord "when" gebruikt. Uiteraard kunnen meerdere condities gespecificeerd worden. Voor een "OR" gebruik je dan de komma "," en voor de "AND" het sleutelwoord "and". Ook "NOT" wordt ondersteund. Hieronder volgt een less-script dat laat zien hoe guards werken.

@screen_width400px;
@green:#0f0;
@red:#f00;

.container (@width) when (@width > 100) and (@width < 600)
{
    color:@green;
}
.container (@width) when (@width =< 100), (@width >= 600)
{
    color:@red;
}

#block1
{
    .container(800px);
}
#block2
{
    .container(500px);
}

Dit script resulteert in het volgende css:

#block1 {
  background-colorred;
}
#block2 {
  background-colorlime;
}
Natuurlijk biedt Less nog veel meer functionaliteiten. Zo kun je namespaces definiëren waarin je mixins plaatst, er is een grote set aan voorgedefinieerde functies en je kunt zelfs javascriptfuncties door Less laten uitvoeren, hoewel dat sterk afgeraden wordt. Meer hierover op de website van Less.

Less is een sterk tooltje waarmee css wordt gegenereerd. Alles wat je in less kunt, zou je natuurlijk ook zonder less kunnen doen. De kracht van Less zit echter in het hergebruik binnen css en de structurering van de code die in css erg gecompliceerd kan zijn. Bovendien kunnen less-scripts opgenomen worden in bundles, een techniek in ASP.NET waarmee meerdere scripts tot één groot script wordt gebundeld, daarmee kostbare round trips besparend. Kortom, een aanrader. 

Geen opmerkingen:

Een reactie posten