n00b pro

06. CSS professionalisering

Dit hoofdstuk is onderdeel van de cursus CSS. Andere cursussen in dezelfde reeks: HTML, Javascript, C#, Ontwikkelomgeving.

Youtube totaaldemo

Deze video's maken deel uit van een HTML + CSS totaaldemo uit de Basic Web Development playlist, die begint met de video BWD 01. HTML - deel 8: praktijkdemo

CSS organisatie en CSS variabelen

https://www.youtube.com/watch?v=9Pa9sBPpsuo

BEM

https://www.youtube.com/watch?v=7ALKCIKN3xA

Selector best practices

sorteer je properties

Sorteer je properties alfabetisch:

.some-element {
   /* merk op hoe de properties gesorteerd zijn van a-z */
   background-color: #A2C355;
   border: 2px solid #A2C355;
   border-radius: 2px;
   color: #fff;
   cursor: pointer;
   display: inline-block;
   font-size: 14px;
   line-height: 18px;
   padding: 9px 24px;
   text-decoration: none;
   text-transform: uppercase;
   transition: background 0.15s, color 0.15s ease-in-out;
}

→ dit helpt je properties sneller terug te vinden en maakt de code leesbaarder

beperk selector lengte

Zoals gezien, heeft selector lengte een invloed op de specificiteit en dus prioriteit. Hoe langer de selector, hoe moeilijker het is de CSS regel te overschrijven met een andere stijl (b.v. in een CSS themabestand). Hou daarom je selectors zo kort mogelijk.

body header > nav.top ul li a {
   ...
}
div#wrapper {
   ...
}
header > nav a {
   ...
}
#wrapper {
   ...
}

→ betere leesbaarheid
→ lager gewicht = makkelijk later te overschrijven met een zwaardere selector indien nodig (b.v. thema)

Organisatie in meerdere stylesheets

Naarmate je website groeit, wordt het steeds onhandelbaarder alle CSS in één bestand te steken. Splits daarom je CSS over meerdere bestanden. Een suggestie (maar denk gerust na over andere opdelingen):

De opdeling voor b.v. een pagina products.html wordt dan

...
<head>
   ...
   <link rel="stylesheet" href="css/start.css">
   <link rel="stylesheet" href="css/common.css">
   <link rel="stylesheet" href="css/products.css">
   ...
</head>
...

→ één groot CSS bestand voor een hele site is op termijn echt geen optie!
→ vermijd dubbele CSS in de verschillende CSS bestanden!

start.css

start.css (of reset.css mag ook) bevat dan alle universeel herbruikbare CSS; een voorbeeld:

/**
* Generic styles
*
* @author Rogier van der Linde <rogier.vanderlinde@odisee.be>
*
*/

/* nuttig voor alle sites */

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}

img {
   max-width: 100%;
}

common.css

common.css (of general.css mag ook) bevat alle CSS gemeenschappelijk voor alle pagina's:

Structureer je stylesheet met commentaar op een consistente manier; voorbeeld:

/**
* Common styles for site <site-name>
*
* @author Rogier van der Linde <rogier.vanderlinde@odisee.be>
*
*/

/* ===========================================
   General
   =========================================== */

/* general layout */

.wrapper {
   margin: 0 auto;
   min-width: 320px;
   max-width: 960px;
   padding: 0 10px;
}

/* element styles */

body {
   font-size: 13px; /* standard font size */
   font-family: verdana, Arial, Helvetica, sans-serif;
   /* ... */
}

a {
   /* ... */
}

p {
   /* ... */
}

h1, h2, h3, h4 {
   /* ... */
}

/* class styles */

.more {
   /* ... */
}

.bigger {
   /* ... */
}

/* ===========================================
   Header
   =========================================== */

/* general */
/* ... */

/* logo */
/* ... */

/* main menu */
/* ... */

/* ===========================================
   Content
   =========================================== */

/* ...content styles... */

/* ===========================================
   Doormat
   =========================================== */

/* general */
/* ... */

/* left column */
/* ... */

/* middle column */
/* ... */

/* right column */
/* ... */

/* ===========================================
   Footer
   =========================================== */

/* ...footer styles... */

/* ===========================================
   Media queries
   =========================================== */

@media (min-width: 30em) { /* 30 * 16 = 480px */
   /* your media queries here */
   /* ... */
}

@media (min-width: 50em) { /* 50 * 16 = 800px */
   /* your media queries here */
   /* ... */
}

somepage.css

Voor de pagina-specifieke stylesheet, bv. products.css, gebruik je dezelfde structuur

/**
* Page-specific styles for the products page
*
* @author Rogier van der Linde <rogier.vanderlinde@odisee.be>
*
*/

/* ===========================================
  General
  =========================================== */

/* general layout */
/* ... */

/* element styles */
/* ... */

/* class styles */
/* ... */

/* ===========================================
  Content
  =========================================== */

/* ...content styles... */

/* ===========================================
  Media queries
  =========================================== */

@media (min-width: 30em) { /* 30 * 16 = 480px */
   /* your media queries here */
   /* ... */
}

@media (min-width: 50em) { /* 50 * 16 = 800px */
   /* your media queries here */
   /* ... */
}

verdere opdeling common.css

Bij grotere sites is het nuttig common.css nog verder op te splitsen, b.v. voor header, navigatie, thema...:

...
<head>
   ...
   <link rel="stylesheet" href="css/start.css">
   <!-- begin common styles -->
   <link rel="stylesheet" href="css/theme.css">
   <link rel="stylesheet" href="css/layout.css">
   <link rel="stylesheet" href="css/header.css">
   <link rel="stylesheet" href="css/menus.css">
   <link rel="stylesheet" href="css/footer.css">
   <!-- end common styles -->
   <link rel="stylesheet" href="css/index.css">
   ...
</head>
...

→ voordeel: je vindt de CSS van de verschillende onderdelen veel makkelijker terug
→ (klein) nadeel: er staan nu wel heel veel stylesheet links in de <head>

one rules them all: @import

Je kan de <head> verlichten door één gemeenschappelijk styles.css te gebruiken, van waaruit je linkt naar de deelbestanden start.css, layout.css, header.css enz... De HTML code wordt veel lichter:

...
<head>
   ...
   <link rel="stylesheet" href="css/styles.css">
   <link rel="stylesheet" href="css/index.css">
</head>
...

styles.css wordt dan:

@import "start.css";
@import "theme.css";
@import "layout.css";
@import "header.css";
@import "menus.css";
@import "footer.css";
...

BEM notatie

De BEM of Block-Element-Modifier notatie biedt een gestructureerde en uniforme manier om met selectoren om te gaan.

problemen met klassieke notatie

Vertrekken we van volgend typisch HTML fragment:

<main>
  ...
   <section>
      <h3>Onze producten</h3>
      <div id="products">
         <div class="product">
            <h4>Bijzettafel</h3>
            <img src="img/prod1.jpg" class="visual" alt="...">
            <p>price: €499,-</p>
            <p class="description">...beschrijving hier...</p>
         </div>
         <div class="product">
            ...
         </div>
         ...
      </div>
   </section>
</main>

Aan de typische manier waarop vervolgens CSS selectors gebruikt worden hangen toch wel wat nadelen:

main > section { /* als je een div in de HTML tussenvoegt, klopt deze regel niet meer */
   ...
}
#products { /* waar staat dit element? main content, sidebar...? */
   ...
}
.product h4 { /* als we een h5 gebruiken i.p.v. een h4, klopt deze regel niet meer */
   ...
}
.description { /* te algemeen; andere elementen zouden ook de class="description" kunnen hebben */
   ...
}
#products .visual + p { /* specifiek genoeg, maar lange en zware selector */
   ...
}

De meeste CSS die vandaag geschreven wordt, lijdt aan deze problemen

BEM notatie oplossing

De BEM (Block-Element-Modifier) naamgeving techniek lost al deze problemen op:

Onze BEM-verbeterde HTML:

<main>
   ...
   <section class="main__products">
      <h3 class="products__title">Our products</h3>
      <div class="products__wrapper">
         <div class="products__product">
            <h4 class="product__title">Magazine table</h3>
            <img class="product__visual" src="img/prod1.jpg" alt="...">
            <p class="product__price">price: €499,-</p>
            <p class="product__description">...description here...</p>
         </div>
         <div class="products__product products__product--highlighted">
            ...
         </div>
         ...
      </div>
   </section>
</main>

De BEM CSS:

.main__products {
   ...
}
.products__wrapper {
   ...
}
.products__product {
   ...
}
.product__title {
   ...
}
.product__visual {
   ...
}
.product__description {
   ...
}
.product__price {
   ...
}
.products__product--highlighted {
   ...
}

→ mooie vlakke CSS
→ iets meer code in de HTML, maar het maakt je CSS zo veel makkelijker

Wees geen BEM nazi! Het is oké BEM te gebruiken wanneer het uitkomt, en het te mixen met klassieke CSS selectors.

CSS variabelen

CSS variabelen laten toe een aantal veel gebruikte kleuren, lettergrootttes e.d. aan variabelen toe te wijzen, die je dan overal in je CSS kan gebruiken. Typisch breng je ze onder in een bestand colors.css; voorbeeld:

:root {
   /* kleur variabelen */
   --primary-color: #3498db;
   --secondary-color: #2ecc71;
   --accent-color: #e74c3c;
   --background-color: #ecf0f1;
   --text-color: #2c3e50;
   
   /* font variabelen */
   --primary-font: 'Helvetica Neue', sans-serif;
   --secondary-font: 'Georgia', serif;
}

Gebruiksvoorbeeld:

/* variabelen gebruiken */
body {
   background-color: var(--background-color);
   color: var(--text-color);
   font-family: var(--primary-font);
}

h1, h2, h3, h4, h5, h6 {
   color: var(--primary-color);
   font-family: var(--secondary-font);
}

a {
   color: var(--accent-color);
}

button {
   background-color: var(--secondary-color);
   color: white;
   border: none;
   padding: 10px 20px;
   font-family: var(--primary-font);
   cursor: pointer;
}

button:hover {
   background-color: var(--primary-color);
}

.footer {
   background-color: var(--primary-color);
   color: white;
   text-align: center;
   padding: 20px;
}