Een kaart maken

Overzicht

Een kaart groepeert één gerelateerd stuk content of één keuze. Het is een visueel patroon, geen vast semantisch of interactiemodel. Behoud dus de betekenis van de content en gebruik de native interactie die bij het doel past.

Richtlijnen

Kies semantiek voor de content en de interactie afzonderlijk:

  • gebruik <article> als de kaartroot, ongeacht of deze naar een bestemming linkt,
  • gebruik een systeemeigen link voor navigatie. Als de hele kaart één bestemming is, mag een enkele link de <article> alleen omvatten als de kaart geen andere interactieve elementen bevat (a, button, input, select, textarea).
  • links en knoppen voor onafhankelijke acties als afzonderlijke systeemeigen bedieningselementen houden,
  • gebruik een keuzerondje of selectievakje met een bijbehorend <label> of een option in een systeemeigen <select> als de kaart een keuze is.

Houd media, titel, ondersteunende content en acties in een logische bronvolgorde. Gebruik geen CSS-order om dit tegen te spreken (zie CSS-indelingen en responsief ontwerp).

Implementatie

Houd de opmaak minimaal en laat css-kiezers elke regio herkennen, zodat eenvoudige kaarten eenvoudig blijven en uitgebreidere kaarten mogelijk blijven. Een kaart heeft maximaal 4 regio's, in deze bronvolgorde. Je kunt ze allemaal weglaten. Regio's zijn directe onderliggende elementen van de kaart en zijn niet gegroepeerd in wrapper-elementen zoals .card__body. Hierdoor kunnen regio's niet worden geplaatst en opgemaakt met een kiezer. Een regio met één element is dat element zelf, niet verpakt: een enkele alinea is de <p>. Gebruik alleen een wrapper als een regio meerdere elementen bevat.

  • Media: een <img>, <picture>, <video> of <svg> als het eerste onderliggende element. Voeg een .media-klasse alleen toe aan willekeurige hero-content die niet een van die elementen is en verpak een gewone <img> nooit in een .media-element.
  • Kop: een kop op zichzelf. Gebruik <hgroup> alleen als de kop een ondertitel of tagline heeft en <header> als de regio meer dan een titel bevat, zoals een auteursregel of badge. Als de kaart een primaire bestemming heeft, staat de link in de kop.
  • Content: een enkele <p>, <ul> of <dl> staat op zichzelf. Als de content uit meerdere elementen bestaat, zoals meerdere alinea's of een alinea plus een lijst, groepeer je ze in één <div> zodat de regio één rasteritem is.
  • Voettekst: een <footer> met onafhankelijke acties als systeemeigen links en knoppen. Een link 'Lees meer' kan de URL van de koplink delen, maar geef deze een beschrijvende, toegankelijke naam die begint met de zichtbare tekst, met visueel verborgen tekst (bijvoorbeeld Read more<span> about poached eggs</span>), omdat identieke links 'Lees meer' dubbelzinnig zijn in de linklijst van een schermlezer. Voeg geen andere footerlinks toe die de URL van de kop herhalen.

De eenvoudigste kaart is een <article> met een kop en een alinea. Kies het link- en actiepatroon dat overeenkomt met het gedrag van de kaart. Zie Interactiemodellen.

Voor kaartafbeeldingen of -video's die een gebied met een vaste verhouding moeten vullen, stel je aspect-ratio en object-fit: cover in op de <img> of <video> zelf, zodat het gebied wordt gevuld zonder vervorming (er kan bijsnijden plaatsvinden). Gebruik de aspect-ratio van een .media-container alleen voor andere hero-content. Behoud anders de intrinsieke verhouding van de media. Geef informatieve afbeeldingen een geschikte alternatieve tekst. Gebruik alt="" voor decoratieve afbeeldingen.

Aanpassen aan de beschikbare ruimte

Baseer de indeling op de beschikbare ruimte van de kaart, niet op het kijkvenster. Als je de afstammelingen van de kaart (media, tekst, acties) wilt aanpassen, maak je van de kaart de groottecontainer (container-type: inline-size) en schrijf je @container-regels voor de onderliggende elementen. Vermijd het aanpassen van de grootte vanuit het bovenliggende element van het raster of de lijst: de werkelijke breedte van de kaart kan afhankelijk zijn van het aantal kolommen, tussenruimtes, enzovoort, waardoor op bovenliggende elementen gebaseerde breekpunten onduidelijk zijn.

In een smalle container stapel je de regio's in de volgorde van de bron. Plaats de media in een brede container in een zijbalk naast de andere regio's, maar alleen voor kaarten met media: pas die regels toe met :has() op het onderliggende media-element (bijvoorbeeld .card:has(> img)), zodat de kolomdefinities en grid-column-plaatsingen nooit van toepassing zijn op een kaart zonder media. Een kaart zonder media blijft bij elke breedte één kolom en mag geen lege mediakolom reserveren.

Kaarten uitlijnen in een raster

Als kaarten in een rij de hoogtes van hun regio's moeten delen, gebruik je subgrid: laat elke kaart 4 gedeelde rijtracks beslaan (media, koptekst, content, voettekst) en plaats regio's per elementkiezer, waarbij je alles wat geen media, kop of <footer> is, behandelt als content. Als een kaart een regio weglaat, blijft de track leeg, zodat de resterende regio's nog steeds op één lijn liggen met aangrenzende kaarten. Elke track bevat één rasteritem. Plaats de contentregio dus alleen in een <div> als deze meer dan één element bevat en kaarten tracks delen. Kaarten die niet zijn uitgelijnd met gerelateerde elementen, hebben geen wrapper of subraster nodig.

Interactiemodellen

Contentkaarten

Gebruik een <article> als de kaartroot. Houd links en knoppen als afzonderlijke native bedieningselementen.

Kaarten met één bestemming

Als de hele kaart één bestemming is en geen onafhankelijke acties heeft, gebruik je één systeemeigen link. De link kan de <article> omvatten. Nest geen andere links, knoppen of formulierbesturingselementen in de link en houd de tekst 'Lees meer' als een gewone <p> of <span>. Omdat de toegankelijke naam van de link de hele tekst van de kaart is, moet je de content kort houden. Als de kaart veel tekst of andere acties bevat, gebruik je het patroon voor uitgerekte links hieronder, zodat alleen de kop de link is:

<a href="/recipes/poached-eggs">
  <article class="card">
    <h3>Poached eggs</h3>
    <p>Two poached eggs served on toasted sourdough.</p>
  </article>
</a>

Klikbare kaarten met onafhankelijke acties

Als een klik op de kaart een actie activeert in plaats van navigatie, gebruik je een <button> in plaats van een link.

Als een contentkaart naar een primaire bestemming linkt, andere interactieve elementen bevat en als geheel klikbaar moet zijn:

  • Gebruik een enkele toestemming op de primaire link zelf: zet .card-link op precies één link per kaart (de link in de kop). Voetteksten en andere links krijgen deze nooit, anders zou elke link een eigen overlay krijgen en zou de laatste de hele kaart in beslag nemen.
  • Koppel de titel en rek het aanwijzergebied uit over de kaart met ::after
.card:has(a.card-link) {
    position: relative;
}

.card a.card-link::after {
    content: "";
    position: absolute;
    inset: 0;
}
  • Verhoog interactieve elementen met position: relative; z-index: 1 zodat ze bedienbaar blijven. Target typen elementen (bijv. a, button) in plaats van aanmelding via klassen te vereisen.
  • Pas z-index NIET toe op hele containers, omdat ze dan aanwijzergebeurtenissen vastleggen die geen actie opleveren.
.card:has(a.card-link) {
    /* Keep other interactive elements above the overlay */
    a:not(.card-link), button, input, x-button {
        position: relative;
        z-index: 1;
    }
}
  • Stijl de kaart zelf bij aanwijzen/focus, in plaats van de uitgerekte link:
.card {
    a.card-link {
        &:focus-visible {
            outline: none; /* Draw it on the card instead */
        }
    }
    
    &:has(a.card-link:focus-visible) {
        /* Focus ring */
    }

    &:has(a.card-link:hover) {
        /* Hover styles */
    }
}

Keuzekaarten

Voor kaarten die vooraf gedefinieerde keuzes vertegenwoordigen, gebruik je <label class="card"> met een selectievakje of keuzerondje als direct onderliggend element.

De geselecteerde kaart opmaken met :has(:checked). Wijzig nooit eigenschappen die de indeling beïnvloeden, zoals border-width, padding of font-weight bij selectie, omdat de kaart en de aangrenzende kaarten dan verspringen. Leg de nadruk met outline, box-shadow of een transparante rand die alleen van kleur verandert:

.card {
  border: 2px solid transparent;

  &:has(> :checked) {
    border-color: var(--accent);
  }
}

Het zichtbare selectievakje of keuzerondje is zelf een niet-kleurindicator van de selectie, dus de kleurwijziging alleen is voldoende. Als de bediening visueel verborgen is (houd deze focusbaar en in de toegankelijkheidsstructuur, nooit display: none), voeg je een niet-kleurindicator toe die geen invloed heeft op de vormgeving, zoals een vinkje of een dikkere outline.

Als keuzes horen bij een dropdownkiezer waarvan de opties zijn ingedeeld als kaarten, gebruik je een native <select> met appearance: base-select en stijl ::picker(select)- en <option>-elementen in plaats van de selectie te vervangen door <div>-kaarten. Ga naar Aangepaste indelingen voor selectiekiezers voor meer informatie en fallbacks.