CSS Syntax

tussen []: optioneel, sterk aanbevolen voor wie wil verdergaan in web

gebruik pijltjestoetsen om te navigeren
dotted codepanels zijn editeerbaar

CSS

Stylesheets

CSS stijlregel

  • CSS of Cascaded Style Sheets bestaat in essentie uit een opsomming van stijlregels met opmaak en layout. Elke stijlregel bestaat uit een selector, een property en een waarde:
    selector {
      property: value;
    }
  • Voorbeeld:
    p {
      color: black;
    }
  • → dit selecteert alle paragrafen, en zet de tekstkleur in zwart

Inline Stijlen

  • Je kan stijlen inline toevoegen, dus rechtstreeks in je HTML, via het style attribuut:
    ...
    <body style="background-color: #f7ba5a">
      <p style="font-size: 18px; margin-left: 20px">
      ...
  • → er is totaal geen scheiding tussen HTML en CSS code
    → gebruik is verboden in deze cursus!

Interne stijlen

  • Je kan stijlen ook intern toevoegen in een <style> blok in de <head>:
    ...
    <head>
      ...
      <style>
        p {
          font-size: 18px;
          margin-left: 20px
        }
        body {
          background-color: #f7ba5a;
        }
      </style>
    </head>
    ...
  • → de scheiding van HTML en CSS code is al beter, maar ze staan nog steeds in hetzelfde codebestand
    → gebruik is verboden in deze cursus!

Extern gelinkte stijlen

  • De beste methode is een apart CSS bestand of stylesheet linken aan je HTML document:
    ...
    <head>
      ...
      <link rel="stylesheet" href="css/styles.css">
      ...
    </head>
    ...
  • Het gelinkte CSS bestand bevat dan de CSS code:
    p {
      font-size: 18px;
      margin-left: 20px;
    }
    body {
      background-color: #f7ba5a;
    }
  • → dit is de juiste manier om CSS te koppelen aan je HTML
    → gebruik is verplicht in deze cursus!

Meerdere stylesheets

  • Je kan zoveel stylesheets linken als je wil:
    ...
    <head>
      ...
      <link rel="stylesheet" href="css/common.css">
      <link rel="stylesheet" href="css/site.css">
      <link rel="stylesheet" href="css/home.css">
      ...
    </head>
    ...
  • → dit laat toe je CSS te organiseren in meerdere bestanden

Media queries

  • Met media queries kan je stijlen beperken tot specifieke media, bv. de breedte:
    @media all {
      body {
        background-color: white;
      }
    }
    
    @media (min-width: 480px) {
      body {
        background-color: #ddd;
      }
    }
    
    @media (min-width: 600px) {
      body {
        background-color: #bbb;
      }
    }
    
    @media (min-width: 768px) {
      body {
        background-color: #999;
      }
    }
    
  • we komen hierop terug in het hoofdstuk over responsive design

CSS commentaar

  • Commentaar:
    /**
    * Main styles
    *
    * @author Rogier van der Linde
    */
    
    p {
      color: black; /* all paragraphs black */
    }

CSS layout (1)

  • Een goede CSS begint bij een degelijke layout:
    • elke property op aparte regels
    • degelijke indentatie
    • een spatie na elk dubbelpunt
    • een open regel na elk blok
    • properties alfabetisch gesorteerd
  • dus niet...
    p { line-height:1.3; color: #333 }
     .box {
       background-color: #666;
       font-size:        12px;
       padding:          10px 20px;
     }
     @media (min-width: 800px) {
     .box {
       padding: 0;
     }
     }

CSS layout (2)

  • ...maar wel:
    p {
       color: #333;
       line-height: 1.3;
    }
    
    .box {
       background-color: #666;
       font-size: 12px;
       padding: 10px 20px;
    }
    
    @media (min-width: 800px) {
      .box {
        padding: 0;
      }
    }
  • tip: gebruik Shift-Alt-F in VS Code (installeer de CSS formatter extensie)

CSS

Selectors

Elementen selecteren

  • Selecteer elementen op basis van tagnaam, class- of id attribuut, of alle:
    p {
      /* tag selector; selecteert <p> */
    }
    .message {
      /* class selector; selecteert <... class="message"> */
    }
    .message.error {
      /* multiple class selector; selecteert <... class="message error"> */
    }
    #lnk-login {
      /* id selector; selecteert <... id="lnk-login"> */
    }
    * {
      /* universele selector; selecteert alle elementen */
    }
  • een id attribuut moet uniek zijn, dus een id selector kan maar één element selecteren
  • een class attribuut hoeft niet uniek te zijn, dus deze selector kan meerdere elementen selecteren

Element toestand

  • Selecteer elementen in een bepaalde toestand:
    a:hover {
      /* selecteert hovered link */
    }
    textarea:focus {
      /* selecteert focused <textarea> */
    }
    input[type=email]:invalid {
      /* selecteert invalid <input type="email"> */
    }
    input:disabled {
      /* selecteert disabled <input> */
    }
  • men noemt dit ook pseudo-class selectoren

Element deel (1)

  • Selecteer een deel van een element:
    a::first-letter {
     /* selecteert de eerste letter van <a> */
    }
    ::selection {
     /* selecteert het deel geselecteerd door de gebruiker */
    }
    li::before {
     content: url(../img/bullet.png); /* injecteer een afbelding aan het begin */
     /* meer properties van de nieuwe content */
    }
    li::after {
     content: "some text"; /* injecteer tekst aan het einde */
     /* meer properties van de nieuwe content */
    }              
  • men noemt dit ook pseudo-element selectoren

Element deel (2)

  • Een voorbeeld met injectie van 👉 en 👈 aan het begin en einde list items:
    <ul>
       <li>item 1</li>
       <li>item 2</li>
       <li>item 3</li>
    </ul>
                
    li {
       list-style: none; /* verwijder standaardbullets */
    }
    li::before {
       content: "👉";
       font-size: 12px;
       margin-right: 5px;
    }
    li::after {
       content: "👈";
       font-size: 12px;
       margin-left: 5px;
    }

Element positie

  • Specifieer de positie van een element:
    h1 + p {
      /* selecteert <p> direct volgend op een <h1> */
    }
    li + li {
      /* selecteert alle <li>'s behalve de eerste */
    }
    li:first-child {
      /* selecteert een <li> die de eerste child is van zijn parent */
    }
    #content > section {
      /* selecteert <section> direct genest in <... id="content"> */
    }
    tr:nth-child(odd) {
      /* selecteert oneven <tr>'s */
    }
    section:nth-child(3n+1) {
      /* selecteert <section>'s nummer 1, 4, 7... */
    }

Element attribuut

  • Selecteer elementen op basis van een attribuut:
    select[multiple] { ... }    /* "heeft", b.v. <select multiple> */
    input[type=button] { ... }  /* "is", b.v. <input type="button"> */
    a[title*=flower] { ... }    /* "bevat", b.v. <a title="...flower..."> */
    img[src^=https://] { ... }  /* "begint met", b.v. <img src="https://..."> */
    a[href$=".pdf"] { ... }     /* "eindigt met", b.v. <a href="....pdf"> */

Selectors combineren

  • Combineer selectors:
    p.message {
      /* tag-class selector; selecteert <p class="message"> */
    }
    nav#mainmenu {
      /* tag-id selector; selecteert <nav id="mainmenu"> */
    }
    #mainmenu.open {
      /* id-class selector; selecteert <... id="mainmenu" class="open"> */
    }
    

Selectors groeperen

  • Groepeer verschillende selectors met dezelfde stijlen in een komma-lijst:
    input {
      color: blue;
    }
    #mainmenu a:hover {
      color: blue;
    }
    p.formpar {
      color: blue;
    }
  • → is hetzelfde als:
    input, #mainmenu a:hover, p.formpar {
      color: blue;
    }

Selectors nesten

  • Een spatie betekent genest in (lees van rechts naar links):
    #leftcol p { /* paragrafen genest in het element met id="leftcol" */
      ...
    }
    nav li.active a { /* links genest in list items met class="active" genest in nav element */
      ...
    }
  • dit was maar een kort overzicht van selectors; voor een overzicht zie de CSS cheatsheet

CSS

Properties

Property lijst

  • Stijlen bestaan uit lijsten property - waarde paren:
    selector {
      property 1: waarde 1;
      property 2: waarde 2;
      property 3: waarde 3;
      ...
    }
    p {
       color: red;
       font-size: 10px;
       margin-bottom: 6px;
    }

Properties groeperen (1)

  • Sommige gerelateerde properties kunnen gegroepeerd worden in een enkele waarde, b.v...
    body {
      background-image: url(../img/bg.jpg);
      background-position: right;
      background-repeat: repeat-y;
    }
    .box {
      margin-top: 6px;
      margin-right: 15px;
      margin-bottom: 6px;
      margin-left: 15px;
    }
    

Properties groeperen (2)

  • ...is hetzelfde als:
    body {
      background: url(../img/bg.jpg) repeat-y right; /* image, repeat, position */
    }
    .box {
      margin: 6px 150x 6px 150x; /* top, right, bottom, left */
    }
    
  • → de volgorde van de waarden moet correct zijn

Propertywaarden met spaties

  • Rond propertywaarden met spaties moeten quotes staan om verwarring te vermijden:
    p {
      font-family: Arial, Verdana, "sans serif";
    }
  • → rond andere waarden zijn quotes niet nodig:
    body {
      background-image: url(img/bg.jpg);
    }
    

Prioriteit en overerving

  • De uiteindelijke stijl van een element wordt bepaald door verschillende factoren:
    • het element kan matchen met verschillende selectoren
    • stijlen kunnen meermaals gedefinieerd zijn in meerdere bestanden
    • sommige stijlen kunnen overerven van de parent (b.v. lettertype)
    • stijlen hebben standaardwaarden afhankelijk van de gebruikte browser
  • Bij conflicterende stijlen, wordt de prioriteit als volgt bepaald (van hoog naar laag):
    1. inline stijlen gedefinieerd in het <style> attribuut hebben altijd de hoogste prioriteit
    2. indien het element matcht met verschillende selectoren dan wint de zwaarste selector (zie verder)
    3. bij gelijk gewicht, wint de laatst gedefinieerde selector
    4. sommige stijlen kunnen worden overgeërfd van de parent (zie verder)
    5. indien geen stijl gedefinieerd is, wordt de browser defaultwaarde genomen

Prioriteit

  • Het gewicht van de selector bepaalt dus de prioriteit, meer dan de volgorde. Als vuistregel geldt: eerst inline styles, dan id selectors, daarna class selectors en tenslotte tag selectors. Neem volgend fragment:
    div#idtest {
      font-size: 12px;
    }
    div.ctest {
      font-size: 14px;
    }
    
  • Volgend element matcht met beide selectoren — wat is dan de font size?
    <div id="idtest" class="ctest">...</div>
    
  • de eerste selector is zwaarder, dus 12px
  • je moet dit uiteraard niet kunnen uitrekenen (al kan het wel); volg je buikgevoel

Overerving

  • Sommige stijlen worden overgeërfd van de parent, vooral visibility en fonts (voor een volledige lijst zie deze pagina). Een voorbeeld:
    body {
      color: #00b;
      font-family: courier;
      border: 5px solid black;
    }
    
    ...
    <body>
      <h2>This is line 1</h2>
      <p>This is line 2</p>
    </body>
    </html>
  • <h2> en <p> erven color en font over van <body>, maar niet border

Tip 1: sorteer je properties

  • Sorteer je properties alfabetisch:
  • .some-element {
      /* kijk nog niet teveel naar de CSS; 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

Tip 2: beperk selector lengte

  • Hou 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)

CSS

Chrome Inspector

CSS inspecteren

  • Inspecteer een element en bekijk de CSS eigenschappen:

Stijl uitschakelen

  • Schakel stijlen tijdelijk in en uit met de checkboxes:

Toegepaste stijlen inspecteren

  • Ontdek welke stijl uiteindelijk van toepassing is, en waarom:

Element state inschakelen

  • Schakel element states als hover en focus in:

Box model inspecteren

  • Bekijk afmetingen en diktes van border, margin en padding:

Waarde aanpassen

  • Experimenteer door andere property waarden uit te proberen:

Properties filteren

  • Vind snel een property via het zoekvenster:

Stijlregel toevoegen

  • Experimenteer door nieuwe stijlregels toe te voegen:

HTML node verwijderen

  • Debug een fout door een HTML node tijdelijk te verwijderen:

CSS

Organisatie

Meerdere stylesheets

  • Een website bestaat uit verschillende HTML pagina's. Splits je CSS over meerdere bestanden. Een suggestie (maar denk gerust na over een andere opdeling):
    • start.css: alle CSS gemeenschappelijk voor alle sites
    • common.css alle CSS gemeenschappelijk voor alle pagina's van deze site
    • index.css, contact.css... alle pagina-specifieke CSS
  • 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 echt geen optie!
  • vermijd dubbele CSS in de verschillende CSS bestanden!

Start.CSS

  • start.css (of reset.css als je wil) bevat alle universeel herbruikbare CSS; een voorbeeld:
    /**
    * Generic styles for site <site-name>
    *
    * @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 bevat alle CSS gemeenschappelijk voor alle pagina's:
    • opmaak voor links, tekst, titels...
    • header met logo, menu...
    • footer
    • algemene media queries
  • 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 */
     /* ... */
    }

Products.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 */
     /* ... */
    }

Common.css opgesplitst

  • Bij grotere sites is het nuttig common.css verder op te splitsen in meer CSS bestanden:
    ...
    <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>

Common.css met @import

  • Je kan de <head> verlichten door common.css te behouden, en van daaruit linken naar de deelbestanden layout.css, header.css enz... met @import:
    ...
    <head>
      ...
      <link rel="stylesheet" href="css/start.css">
      <link rel="stylesheet" href="css/common.css">
      <link rel="stylesheet" href="css/index.css">
      ...
    </head>
    ...
    @import "theme.css";
    @import "layout.css";
    @import "header.css";
    @import "menus.css";
    @import "footer.css";
    ...

[De BEM notatie (1)]

  • De BEM of Block-Element-Modifier notatie biedt een gestructureerde en uniforme manier om met selectoren om te gaan. 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>
    

[De BEM notatie (2)]

  • ...typisch zou je selectors gebruiken als:
    main > section {
      ...
    }
    #products {
      ...
    }
    .product h4 {
      ...
    }
    .visual {
      ...
    }
    .description {
      ...
    }
    #products .visual + p {
      ...
    }

[De BEM notatie (3)]

  • De meeste CSS is zo geschreven, en dat is oké.
  • Er zijn een paar nadelen toch:
    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 geneog, maar lange en zware selector */
      ...
    }

[De BEM notatie (4)]

  • De meeste CSS lijdt aan deze problemen:
    • de CSS is te afhankelijk van de precieze HTML structuur
    • de selectors missen betekenis en context
    • de selectors zijn niet uniek genoeg, en kunnen onbedoeld conflicteren met andere elementen
    • als de selectors specifiek genoeg zijn, worden ze snel te lang, zwaar en complex
  • Overweeg de BEM (Block-Element-Modifier) naamgeving techniek:
    • gebruik altijd standaard class selectors; vermijd andere selectors als id, tag, attribuut, ...
    • gebruik block__element--modifier conventie:
      • block: de parent of context van het element
      • element: beschrijving van het element
      • modifier (optioneel): toestand (b.v. open/dicht) of thema (b.v. groen/blauw)

[De BEM notatie (5)]

  • 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 notatie (6)]

  • ...en 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!
    → maar: wees geen BEM nazi; het is oké beide technieken te mixen
Odisee logo