Cards

A Card is a flexible and extensible content container. Based on Bootstrap 4’s Card component, our Card provides a containing unit for structured content and a foundation for future contextual uses like News, Contact and Place Cards.

Usage

Look at the View tab for each card variation to see an example of how it is being used.

Macro reference

Card( options )

Default Card component.

Param Default Values Description
class miz-card String Additional classes appended to the card
attributes null Object Attributes to be applied to the card
contents null String or Array The content to be displayed on the card

Structured contents

The contents of a Card can be passed as a simple string or as a structured array of objects.

Use a value of body, title, subtitle, text, image or links to return standard markup and styles.

{
  "contents": [
    {
      "type": "...",
      "contents": "..."
    }
  ]
}
Type Class Required values
body miz-card__body String OR another array of structured contents
title miz-card__title content => String
subtitle miz-card__subtitle content => String
text miz-card__text content => String
image miz-card__image src => Path to image, alt => Alt text
links miz-card__links content => Array of Link Objects containing href and text values

See examples for code samples.

CardGroup( options )

Use Card Groups to render Cards as a single, attached component with equal width and height columns.

Param Default Values Description
class miz-card-group String Additional classes appended to the card
attributes null Object Attributes to be applied to the card
items null Array An array of cards
{#
  Card
  Base Card component.
  @see    https://getbootstrap.com/docs/4.2/components/card/
  @see    https://designsystem.missouri.edu/components/detail/cards.html

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @uses   CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    ├─ options.contents   Value is passed to the CardContents macro for handling. See CardContents for param details.
  @param  {array}     └─ options.contents[]

 #}
{% macro Card( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}
    {% from "@miz/components/cards/cards.twig" import CardContent as cardContent %}

    {# Parameters #}
    {% set cardClass      = 'miz-card' %}
    {% set cardClass = options.class
      ? utils.AppendClasses( cardClass, options.class )
      : cardClass %}
    {% set cardAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardContents = options.contents %}

  {% endspaceless -%}

  {# Output #}
  <div class="{{ cardClass }}" {{ cardAttributes }}>
    {{ cardContent( cardContents ) }}
  </div>

{% endmacro %}

{#
  Card Content
  Handles and outputs most Card content blocks. Returns a string containing content for a single Card or Card Body.
  @see    See Content type macros for other options available.

  @uses   CardBody, CardTitle, CardSubtitle, CardText from @miz/components/cards/cards.twig
  @usedby Card, CardBody from @miz/components/cards/cards.twig

  @param  {string}    contents Can contain either a string, which is simply output as-is OR
  @param  {array}     contents[] An array of strings OR objects that are iterated over and handled through specific content type macros.
  @param  {string}    ├─ contents[].type     - required 'body'|'title'|'subtitle'|'text'
  @param  {string}    └─ contents[].content  - Depending on the kind of content type referenced in the 'type' key, different values may be required. See accompanying macro for more information and available options.

  @return {string}  Returns a string containing the content for a single Card or Card Body.

 #}
{% macro CardContent( contents ) %}
  {% spaceless %}

    {# Imports #}
    {% from "@miz/components/cards/cards.twig" import CardBody as cardBody %}
    {% from "@miz/components/cards/cards.twig" import CardLinkContainer as cardLinkContainer %}
    {% from "@miz/components/cards/cards.twig" import CardTitle as cardTitle %}
    {% from "@miz/components/cards/cards.twig" import CardSubtitle as cardSubtitle %}
    {% from "@miz/components/cards/cards.twig" import CardText as cardText %}
    {% from "@miz/components/cards/cards.twig" import CardImage as cardImage %}
    {% from "@miz/components/cards/cards.twig" import CardLinks as cardLinks %}

    {# Parameters #}
    {% set cardContents = contents %}

    {# Variables #}

    {# Set this for use later. It holds each content block as it's returned for passing along to Card. #}
    {# {% set cardContents = "" %} #}

    {% if cardContents is iterable %}

      {# Loop through content objects #}
      {% for content in cardContents %}

        {% if content.type == 'body' %}
          {{ cardBody( content ) }}
        {% elseif content.type == 'link-container' %}
          {{ cardLinkContainer( content ) }}
        {% elseif content.type == 'title' %}
          {{ cardTitle( content ) }}
        {% elseif content.type == 'subtitle' %}
          {{ cardSubtitle( content ) }}
        {% elseif content.type == 'text' %}
          {{ cardText( content ) }}
        {% elseif content.type == 'image' %}
          {{ cardImage( content ) }}
        {% elseif content.type == 'links' %}
          {{ cardLinks( content ) }}
        {% else %}
          {{ content|raw }}
        {% endif %}

      {% endfor %}

    {% else %}
      {{ cardContents }}
    {% endif %}

  {% endspaceless %}

{% endmacro %}

{#
  Card Body
  Returns a Card Body content type.

  @uses   AppendClasses, AddAttributes from @miz/utilities/utils.twig
  @uses   CardContents from @miz/components/cards/cards.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    ├─ options.content    Can contain either a string OR an object. Strings are output as-is with no handling.
  @param  {array}     └─ options.content[]  An array of strings OR objects that are iterated over and handled through specific content type macros.

 #}
{% macro CardBody( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}
    {% from "@miz/components/cards/cards.twig" import CardContent as cardContent %}

    {# Parameters #}
    {% set cardBodyClass      = "miz-card__body" %}
    {% set cardBodyClass = options.class
      ? utils.AppendClasses( cardBodyClass, options.class )
      : cardBodyClass %}
    {% set cardBodyAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardBodyContents = options.contents %}

  {% endspaceless -%}

  {# Output #}
  <div class="{{ cardBodyClass }}" {{ cardBodyAttributes }}>
    {{ cardContent( cardBodyContents ) }}
  </div>

{% endmacro %}

{#
  Card Link Container
  Returns a Card Link to place content inside, much like a card body.

  @uses   AppendClasses, AddAttributes from @miz/utilities/utils.twig
  @uses   CardContents from @miz/components/cards/cards.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    ├─ options.href       Link to be placed inside the <a href=""> value.
  @param  {string}    ├─ options.content    Can contain either a string OR an object. Strings are output as-is with no handling.
  @param  {array}     └─ options.content[]  An array of strings OR objects that are iterated over and handled through specific content type macros.

 #}
{% macro CardLinkContainer( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}
    {% from "@miz/components/cards/cards.twig" import CardContent as cardContent %}

    {# Parameters #}
    {% set cardLinkContainerClass       = "miz-card__link-container" %}
    {% set cardLinkContainerClass = options.class
      ? utils.AppendClasses( cardLinkContainerClass, options.class )
      : cardLinkContainerClass %}
    {% set cardLinkContainerAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardLinkContainerHref = options.href
      ? options.href
      : "#" %}
    {% set cardLinkContainerContents = options.contents %}

  {% endspaceless -%}

  {# Output #}
  <a href="{{ cardLinkContainerHref }}" class="{{ cardLinkContainerClass }}" {{ cardLinkContainerAttributes }}>
    {{ cardContent( cardLinkContainerContents ) }}
  </a>

{% endmacro %}

{#
  Card Title
  Returns a Card Title content type

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    └─ options.content

  @todo   Possibly add an option for defining the element used if an explicit one is too limiting.

 #}
{% macro CardTitle( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardTitleClass      = "miz-card__title" %}
    {% set cardTitleClass = options.class
      ? utils.AppendClasses( cardTitleClass, options.class )
      : cardTitleClass %}
    {% set cardTitleAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardTitleContent = options.content
      ? options.content
      : "No content found." %}

  {% endspaceless -%}

  {# Output #}
  <h2 class="{{ cardTitleClass }}" {{ cardTitleAttributes }}>
    {{- cardTitleContent -}}
  </h2>

{% endmacro %}

{#
  Card Subtitle
  Returns a Card Subtitle content type

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    └─ options.content

  @todo   Possibly add an option for defining the element used if an explicit one is too limiting.

#}
{% macro CardSubtitle( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardSubtitleClass      = "miz-card__subtitle" %}
    {% set cardSubtitleClass = options.class
      ? utils.AppendClasses( cardSubtitleClass, options.class )
      : cardSubtitleClass %}
    {% set cardSubtitleAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardSubtitleContent = options.content
      ? options.content
      : "No content found." %}

  {% endspaceless -%}

  {# Output #}
  <h3 class="{{ cardSubtitleClass }}" {{ cardSubtitleAttributes }}>
    {{- cardSubtitleContent -}}
  </h3>

{% endmacro %}

{#
  Card Text
  Returns a Card Text content type

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {object}    └─ options.content

  @todo   Possibly add an option for defining the element used if an explicit one is too limiting.

#}
{% macro CardText( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardTextClass      = "miz-card__text" %}
    {% set cardTextClass = options.class
      ? utils.AppendClasses( cardTextClass, options.class )
      : cardTextClass %}
    {% set cardTextAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardTextContent = options.content
      ? options.content
      : "No content found." %}

  {% endspaceless -%}

  {# Output #}
  <p class="{{ cardTextClass }}" {{ cardTextAttributes }}>
    {{- cardTextContent -}}
  </p>

{% endmacro %}

{#
  Card Links
  Returns a Card Link content type

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {array}     └─ options.links

  @todo   Possibly add an option for defining the element used if an explicit one is too limiting.

#}
{% macro CardLinks( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardLinksClass      = "miz-card__link" %}
    {% set cardLinksClass = options.class
      ? utils.AppendClasses( cardLinksClass, options.class )
      : cardLinksClass %}
    {% set cardLinksAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardLinksContent = options.content is iterable? options.content %}

  {% endspaceless -%}

  {# Output #}
  <p class="miz-card__links">
    {% for cardLink in cardLinksContent %}
      {% if cardLink.text is not empty %}
        <a href="{{ cardLink.href }}" class="{{ cardLinksClass }}">{{ cardLink.text }}</a>
      {% endif %}
    {% endfor %}
  </p>

{% endmacro %}

{#
  Card Image
  Returns a Card Image content type

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {string}    ├─ options.src
  @param  {string}    └─ options.alt

#}
{% macro CardImage( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardImageClass      = "miz-card__image" %}
    {% set cardImageClass = options.class
      ? utils.AppendClasses( cardTextClass, options.class )
      : cardTextClass %}
    {% set cardImageAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardImageSrc = options.src
      ? options.src
      : "" %}
    {% set cardImageAlt = options.alt
      ? options.alt
      : "No alt text provided." %}

  {% endspaceless -%}

  {# Output #}
  <img class="miz-card__image" src="{{ cardImageSrc }}" alt="{{ cardImageAlt }}">

{% endmacro %}

{#
  Card Group
  Returns a Card Group

  @uses   AppendClasses, AddAttributes from @miz/utilties/utils.twig
  @usedby CardContents from @miz/components/cards/cards.twig

  @param  {object}    options
  @param  {string}    ├─ options.class
  @param  {object}    ├─ options.attributes
  @param  {array}     └─ options.items

#}
{% macro CardGroup( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}
    {% from '@miz/components/cards/cards.twig' import Card as card %}

    {# Parameters #}
    {% set cardGroupClass       = 'miz-card-group' %}
    {% set cardGroupClass = options.class
      ? utils.AppendClasses( cardGroupClass, options.class )
      : cardGroupClass %}
    {% set cardGroupAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardGroupItems = options.items %}

  {% endspaceless -%}

  {# Output #}
  <div class="{{ cardGroupClass }}">
    {% for item in cardGroupItems %}
      {{ card(item) }}
    {% endfor %}
  </div>
{% endmacro %}

{% macro ContactTitle( options ) %}
  {%- spaceless %}

    {# Imports #}
    {% import "@miz/utilities/utils.twig" as utils %}

    {# Parameters #}
    {% set cardContactTitleClass      = "miz-card__contact--title" %}
    {% set cardContactTitleClass = options.class
      ? utils.AppendClasses( cardContactTitleClass, options.class )
      : cardContactTitleClass %}
    {% set cardContactTitleAttributes = options.attributes
      ? utils.AddAttributes( options.attributes ) %}
    {% set cardContactTitleContent = options.content
      ? options.content
      : "No content found." %}

  {% endspaceless -%}

  {# Output #}
  <h3 class="{{ cardContactTitleClass }}" {{ cardContactTitleAttributes }}>
    {{- cardContactTitleContent -}}
  </h3>

{% endmacro %}

        
    
/* No context defined for this component. */
  • Content:
    ////
    /// Cards
    /// Classes and utilities for use with the Card component.
    ///
    /// @author <Jason Rollins rollinsj@missouri.edu>
    ///
    ////
    
    /// Base Card style
    .miz-card {
      position: relative;
      display: flex;
      flex-direction: column;
      min-width: 0;
      word-wrap: break-word;
      background-color: $miz-card__background-color;
      background-clip: border-box;
      border: $miz-card__border-width;
      border-style: $miz-card__border-style;
      border-color: $miz-card__border-color;
      border-radius: $miz-card__border-radius;
      font-size: 0.8em;
    
      > hr {
        margin-right: 0;
        margin-left: 0;
      }
    }
    
    /// Card Body
    /// Use this class to place content inset into the Card.
    .miz-card__body {
      flex: 1 1 auto;
      padding: $miz-card__body-space;
    }
    
    /// Card Title
    /// Use this class on the main title for the Card
    .miz-card__title {
      margin: $miz-space-stack-default;
    }
    
    /// Card Subtitle
    /// Use this as a subtitle or subheading for a Card.
    /// Do not use without a Title
    .miz-card__subtitle {
      font-size: 1.25em;
      font-weight: $miz-font-weight-bold;
      margin-top: -$miz-card__space-y / 2;
      margin-bottom: $miz-headings-margin-bottom / 2;
    }
    
    /// Card Text
    /// Use this as a class on Card body text.
    .miz-card__text {
      font-size: 1.25em;
    
      &:last-child {
        margin-bottom: 0;
      }
    }
    
    /// Card Image
    /// Use this on images placed in Cards for the image
    /// to fill the Card's space.
    .miz-card__image {
      width: 100%;
      border-radius: 0;
    }
    
    .miz-card__links {
      display: flex;
      flex-wrap: wrap;
      margin-bottom: 0;
    }
    
    .miz-card__link {
      font-size: 1.25em;
      font-weight: $miz-font-weight-bold;
      text-decoration: none;
      border-bottom: $miz-size-xxs solid $miz-gold;
      margin: 0 $miz-space-m $miz-space-m 0;
    
      &:hover {
        border: 0;
      }
    }
    
    .miz-card__header {
      padding: $miz-card__space-y $miz-card__space-x;
      margin-bottom: 0;
    
      > :last-child {
        margin-bottom: 0;
      }
    }
    
    .miz-card__footer {
      padding: $miz-card__space-y $miz-card__space-x;
    
      > :last-child {
        margin-bottom: 0;
      }
    }
    
    /// Card Group
    /// Surround Cards with a container using this class
    /// to create a horizontal group of cards (small screens and up)
    .miz-card-group {
      display: flex;
      flex-direction: column;
    
      @include media-breakpoint-up(sm) {
        flex-flow: row wrap;
    
        > .miz-card {
          flex: 1 0 0%;
          margin-bottom: 0;
        }
      }
    }
    
    ///
    /// Utilities
    
    /// Card theming
    /// Experimental!
    /// Document and refine at a later time.
    .miz-card--dark {
      background-color: $miz-card__background-color--dark;
    }
    
    .miz-card--dark .miz-card__link {
      color: $white;
    }
    
    /// Card Outline
    /// Add a simple border outline to the card.
    .miz-card--outline {
      border: $miz-size-xxs solid $miz-black-100;
    }
    
  • URL: /components/raw/miz-cards/_cards.scss
  • Filesystem Path: fractal/pattern-library/miz/components/cards/_cards.scss
  • Size: 2.7 KB