Design Systems

What is it?

A design system is the reference manual or collection of rules for designing websites that all share a common look and feel.

It defines how space is used, which fonts and font sizes are used when and where, how input elements look and behave, which colors are used when and where and all other aspects that should be part of the common experience.

A design system should incorporate a Coorporate Identity design if it exists. A design system will extend the coorporate identity into the interactive digital space.

It should be based on the principals of human machine interactions based on computer science work to make it easy for a user to benefit from the digital system.

Examples

Tools

CSS Grid Systems

What is a Grid System?

A grid system is a layout mechanism, which makes it an alternative to the CSS Flexbox Layout (aka. flexbox) and the CSS Grid Layout (aka. CSS grid).

Whereas both the CSS Flexbox Layout and the CSS Grid Layout are part of the CSS specification, a grid system is built using CSS functionality and it does exist in the CSS specification. As such there are numerous frameworks that each come with their own implementation of a grid system.

Certain features are common to all grid system. The features are described in detail later.

Difference between Grid System, CSS Grid Layout and CSS Flexbox Layout

Despite the naming similarities, a grid system is not to be confused with the CSS Grid Layout.

I think they do similar things but I could not figure out how they differ or if CSS Grid Layout is there to replace custom grid systems. Need more expertise.

On the twitter boostrap page for their grid system, it says that the grid system is implemented using the CSS Flexbox Layout!

What does a Grid System do?

A Grid System ultimately sizes and positions elements in a responsive fashion. The promise is, when done right, all elements will be assigned appropriate screen space across all viewport size possible. The benefit is that there is always enough width assign so the use can consume the content with maximum convenience.

In a grid systen, elements are put into rows. All rows have the same amount of columns. The amount of columns in bootstrap’s grid system is 12 for example. Other amounts of columns are possible.

Elements are assigned (different) column widths based on media queries. On viewport size changes, elements will take up a dynamic amount of columns because of what the user has defined for each query. On large screen sizes, an element might take up 3 columns for example. In a media query for smaller device, it maybe takes up 6 columns so it is still visible. In a media query for smartphones, it might even take up all 12 columns so it stretches an entire row’s width and the user can still make out its content nicely even though the screen is very small.

Elements, once placed into a row, will never leave that row. If the amount of columns are used up and there are still more elements to place into a row, the row will break and elements will start to stack on top of each other so they do not leave the row.

This most often happens when elements are assign higher column counts on media queries for smaller screens. This keeps rows separate from other rows at all times.

In most grid systems, the media-queries are predefined with standard breakpoints and are called xs, s, m, l and xl similar to clothing sizes. The xs media-query is for very small screen sizes such as mobile phones, xl is for desktop screens.

To define the amount of columns per media-query, a grid system usually defines CSS classes. Several of those CSS classes are then assigned to elements until the user has described the element columns in all media-queries. The CSS classes have no effect unless their media-query actives, which is when the CSS class has an effect on the element. It will then tell the grid-system how many columns the element consumes. 

SCSS Cheatsheet

Comments

CSS comments use the /* … */ syntax. CSS comments are part of a CSS file and will be sent over the internet to the client.

SCSS adds another syntax // …

SCSS syntax are not copied into the resulting CSS. They are therefore not send to the client. This allows you to keep the CSS files as small as possible while still having good documentation in the source files.

Variables

When using the same value, instead of placing independant values all over the stylesheet, consider using a variable for easier maintenance in the future.

Variables start with the $ symbol. A variable definition creates a new variable identifier and assigns a value to that identifier.

$primary-color: #1875e7;
h1#brand { color: $primary-color; }
sidebar { background-color: $primary-color; }

Variables can be used after declaring them. To use a variable, add the $ followed by the identifier in place of a concrete value.

Variables have scope which means the location a variable where is declared determines it’s visibility. A variable can be defined outside any rule, which makes it globally visible amongst all SCSS files. Defining a variable inside a SCSS rule limits it’s visibility to the rule and the nested rules within that rule.

Nesting

SASS allows you to nest selectors and properties.

Nesting for Selectors

CSS allows to chain elements in selectors to specify how to style nested elements that match that path defined in the selector. Basically a selector is a flattened representation of a tree structure. SCSS brings back the tree structure using nesting and saves some redundant typing.

To style elements on several levels of the same nesting hierarchy, you have to write the path over and over to extend it by another level until you have written all rules for all hierarchy levels you want to apply styles to.

SCSS allows you to nest rules to more naturally work with nested elements and their CSS. Instead of 

header: { color: red; }
header a: {
font-weight: bold;
text-decoration: none;
}

you write

#header {
color:red;
a {
font-weight: bold;
text-decoration: none;
}
}

Nesting for Properties

Imagine styling a border with the exploded notation for demonstration purposes:

div {
border-width: 1px;
border-style: solid;
border-color: black;
}

The redundant part here is the border- prefix repeated for all properties.

With property nesting, you split at the dash and add a colon to the root property. Then write the part after the dash into the nested rule like so:

div { 
border: {
width: 1px;
style: solid;
color: black;
}
}

The Parent Operator &

The & operator refers the direct parent in nested rules.

Imageine to following HTML:

<ul>
<li>list element 1</li>
<li class="selected">list element 2</li>
<li>list element 3</li>
</ul>

The list element having the selected class should be displaying in a darker color. With CSS you write several rules, with SCSS, nesting can be used which also allows for the use of the & operator.

ul { border: 1px solid green; }
ul li { color: #DCDCDC; }
ul li.selected { color: #808080; }

In SCSS, the same can be written using nesting.

ul {
border: 1px solid green;
li {
color: #DCDCDC;
&.selected {
color: #808080;
}
}
}

Here, the & refers to the li element because li is the immediate parent for the rule where & was applied. & will be replaced by li after the SCSS compiler produced the output.

The & operator prevents SASS from adding a space between the parent and the child when flattening out the CSS. Adding the & operator will concatenate the elements instead of joining them with a space in between. This is useful for class-based selectors and for pseudo classes.

The CSS Operators >, + and ~

Without using the child combinator (>), CSS rules are applied over more than one level of nesting. Using the > operator, the CSS rule is applied over exactly one level of nesting, which introduces the concept of an immediate child.

The sibling operator (~) selects any following element regardless of how many elements are in between.

The adjacent sibling operator (+) introduces the concept of an immediate sibling, which is the sibling directly following an element.

With SASS, the operators >, + and ~ can be applied at the end of a parent element or at the beginning of a child element.

Mixins

Mixins are defined using the @mixin keyword and they are applied using the @include keyword.

A mixin is a container that can be filled with SCSS rules. When the mixin is applied, all SCSS rules inside it are pasted to that location. In a sense, mixins are similar to variables in that they are a central point to store information and allow for the reuse of that information in several locations.

To define a mixin container use the following syntax:

@mixin <MIXIN_IDENTIFIER>(<PARAMETER>: <DEFAULT-VALUE>, ..., <PARAMETER>: <DEFAULT-VALUE>) {
<SCSS-RULES GO HERE>
}

Applying the mixin is done like this:

@include <MIXIN_IDENTIFIER>(<VALUE>, ..., <VALUE>);

When you have no need to parameterize a mixin, you can leave out the parameter list as it is optional.

TODO: add an example for a beneficial, real-world use of mixins

CSS Animations

This post is supposed to be a beginners introduction to CSS 3 animations. There are two ways for animation in CSS 3, animations and transitions.

Differences between Animations and Transitions

This article sums it up nicely: https://www.peachpit.com/articles/article.aspx?p=2300569&seqNum=2

In general transitions are defined by a start and an end state. Animations can have an arbitrary amount or keyframes in between a start and a end state. Transitions are therefore suited for simpler use-cases, whereas animations are used when the requirement is complex.

Animations

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations

The main use-case for animations is

For animations, a trigger is optional. A animation can start without a trigger for example right after the page loads.

Animations can be created via .css files or via the element.animate() javascript WebAPI (https://developer.mozilla.org/en-US/docs/Web/API/Element/animate).

Transitions

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions

The main use-case for transitions is highlighting items such as navigation elements on hover. Instead of instantly switching the background color of such a navigation element to a darker shade, the transition can smoothly transition the color to the darker shade which gives the page a more relaxed and more organic feel.

A transition needs a trigger to run. This trigger can be the change of a CSS property or some JavaScript.

Transitions are added to CSS classes. A transition lists the properties of the same CSS class, that should be changed in a smooth animation. A animation always need a new value for a property so that a property can be animated as it transitions from the current value to the new value. The new value is not defined by the transition, in other words is not predefined. When a property, that is defined in the list of transitions, changes either by adding or removing a css class or using javascript, then the transition is triggered and will be applied so that the value is smoothly interpolated between the current and the new value.

Transitions are controlled using the transition-properties inside a CSS class. The transition properties are: transition-propertytransition-durationtransition-timing-function and transition-delay.

A shorthand notation is available that combines all properties above into a single line: transition: <property> <duration> <timing-function> <delay>;

Style a Image Slider

Introduction

By image slider, a component that displays a single image out of a set of images is meant. The slider contains controls to switch to a different image. The slider can be controlled via direct user input or indirectly via a timer that automatically operates the image slider.

The Purpose of a slider is similar to an automated marketing presentation or sales video. It is there to catch a visitor, generate attention and interest and to advertise an idea or product to a user that generally has no time to loose.

Features

Features of a slider are:

  • Display an array of images
  • Width, height, general responsiveness
  • Dotted button navigation, minimum, maximum amount of dots
  • Left-right arrow button navigation
  • Mouse- or Thumb Drag navigation (swipe left and right) 
  • Navigation wrap-around
  • Cooldown/Countdown timer that initiates the next transition automatically
  • User interaction with the dotted button navigation will interrupt the automated timer to give the user time. The timer will take over again after some time.
  • Transition default direction or pattern (To-Right, To-Left, Random, …)
  • Animation options for the transition between images (slide, shrink, grow, opacity, alpha, …)

Minimum Viable Product – MVP

Creating an MVP that contains the subset of all features that constitutes the bare minimum to be recognized by a user as a usable component that has benefit, is a strategy to arrive at a result without getting side-tracked and loosing focus.

Why is an MVP important? In short, the main problem is our limited experience when approaching a topic for the first time. Because of all the unknown road blocks a beginner will face on his learning journey, there is natural delay and natural feature creep. Features creep in because unknown requirements pop up and features have to be added to even get the most limited MVP working.

The image slider MVP will 

  • Display three images
  • Contain no navigation
  • Transition between images on click on the current image
  • Transition direction is fixed: to-right is used
  • Contains no wrap-around
  • The transition is not animated, the images just are exchanged
  • The slider is not responsive

MVP Implementation

The HTML markup contains the three slides

<div class="wrapper">
<div class="slides">

<div class="slide active">
First
<img src="../img/mountain-1.jpeg">
</div>

<div class="slide">
Second
<img src="../img/mountain-2.jpeg">
</div>

<div class="slide">
Third
<img src="../img/mountain-3.jpeg">
</div>

</div>
</div>

The CSS contains general styling for the slides which sets all slides into th e display:none state which hides all slides. in addition it contains a CSS class called active. This active class sets display:block on one of the slides to show that slide.

html, body {
width: 100%;
height: 100%;
}

.wrapper {
height: 100%;
}

.slides {
display: flex;
align-items: center;
justify-content: center;
}

.slide {
display: none;

width: 100px;
height: 100px;
background-color: red;
}

.slide.active {
display: block;
}

The JavaScript script registers a click listener on the slides container. In the click listener, the active slide is retrieved and based on the active slide, the indexes for the next slide are computed.

When the next index is computed, the active class is toggled both on the current and on the next slide, which will exchange the images.

function transition() {

// select the slides container element
let slidesElement = document.querySelector('.slides');

// select the NodeList of all slides
let slideElementsArray = slidesElement.querySelectorAll('.slide');

slidesElement.addEventListener('click', () => {
// select the active slide element
let activeSlideElement = slidesElement.querySelector('.active');

// use the prototype as a NodeList has no indexOf() method
let currentSlideElementIndex = Array.prototype.indexOf.call(slideElementsArray, activeSlideElement);

// find the next index
let nextSlideElementIndex = currentSlideElementIndex == slideElementsArray.length-1 ? currentSlideElementIndex : currentSlideElementIndex + 1;

// retrieve the next div element
let nextSlideElement = slideElementsArray[nextSlideElementIndex];

// toggle the active classes to display the next image
activeSlideElement.classList.toggle('active');
nextSlideElement.classList.toggle('active');
})
}

transition();

Style a FlipCard

Links

https://www.w3schools.com/howto/howto_css_flip_card.asp

Introduction

This post contains may notes on the example of a flip card from W3Schools here. The article is not written in a beginner friendly way, I personally feel. It could do with more text describing what each part of the markup and CSS does which this article tries to add.

FlipCards

A FlipCard is a rectangular area that has a front- and a back side. The 3D capabilities of CSS are used to turn the card around by 180 degrees to reveal the card’s flipside. This adds an interesting and interactive effect to a page and also saves some space for detailed information on the item displayed on the front of the card. 

Strategy

The HTML markup contains an outer div that is used to position the flip-card on the page.

Inside the outer div, there is an inner div which will rotate on hover. That inner div contains two nested divs. One is called front-side, the other one is called back-side. Both the front- and back-side are set to not render their back-facing side, that means, when the back-facing side faces the viewer, that side is not rendered by the browser.

Initially the nested front-side is not rotated or rotated by 0 degrees, whereas the back-side is initially turned around, so it is initially rotated by 180 degrees. The front- and back-side are not rotated any more from here on out, only the inner div is rotated.

HTML Markup

<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://picsum.photos/300/200" alt="Avatar" style="width:300px;height:100%">
</div>
<div class="flip-card-back">
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
</div>

You can see the outer flip-card to position the entire card and the inner flip-card that contains the front and back side divs.

CSS Styling

The outer flip-card contains the dimensions and the perspective attribute which introduces a real 3D rotation effect.

.flip-card {
background-color: transparent;
width: 300px;
height: 300px;
border: 0px solid #f1f1f1;
perspective: 1000px;
}

The inner flip-card has two styles, on normal style and one style on hover.

/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}

/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner {
/* On hover, rotate the inner card which will rotate the front and backside with it */
transform: rotateY(180deg);
}

The nested front- and back-side share some styles but also have styles specifically for themselves. One important specific style is the initial rotate of either 0 degrees or 180 degress.

/* Position the front and back side */
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden; /* Safari */
backface-visibility: hidden;
}

/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #bbb;
color: black;
/* initially not rotated */
transform: rotateY(0deg);
}

/* Style the back side */
.flip-card-back {
background-color: dodgerblue;
color: white;
/* initially rotated by 180 degree */
transform: rotateY(180deg);
}

Style a Checkbox as Toggle

Links

https://codepen.io/himalayasingh/pen/EdVzNL

What is this article about?

I found this wonderful codepen created by Himalaya Singh. In this pen, Himalaya takes a HTML checkbox and changes it into an ios style toggle button using pure CSS without any JavaScript. This is quite the useful codepen and this article contains my notes on how to best read and understand Himalaya’s CSS.

The CSS and HTML snippets in this article are not Himalaya’s original code (but still heavily inspired by it). I slightly modified the snippets during my analysis for the worse. So definitly check Himalaya’s original codepen after reading this article.

How it works

The overall strategy is to use a HTML input of type checkbox and then to hide it using an opacity of 0. That way the user cannot see the input but they can still interact with it.

In a second step, a so-called knob and a background layer are added to the toggle. The knob is moving from left to right and displays the checked state of the input. It also can contain a text. The layer acts as a visual border for the input. Both the knob and the layer contain a color.

The HTML input type checkbox has two states, checked and unchecked. CSS classes are used via a selector that selects both possible states. Within the CSS classes for each state, the knob and the layer are styled. A CSS transition is used to define how the styling changes when the input transitions between both of it’s states.

HTML and Styling 

A HTML input with type checkbox is created.

<div class="button r" id="button-1">
<input type="checkbox" class="checkbox">
<!--<div class="knobs"></div>-->
<!--<div class="layer"></div>-->
</div>

We’ll take care of the knob and the layer later.

The surrounding button is positioned.

.button
{
position: relative;
top: 50%;
width: 74px;
height: 36px;
margin: -20px auto 0 auto;
overflow: hidden;
}

Then the input element is styled. To hide the input, an opacity of 0 is used.

/* opacity 0 is entirely transparent, this hides the checkbox but lets the user interact with it still */
.checkbox
{
position: relative;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
opacity: 0;
cursor: pointer;
z-index: 3;
}

At this point you will absolutely see nothing any more on your page. To add graphical representation back, let’s start by adding the knob.

It is important to start with the knob because the knob is what gives the layer content. Starting with the empty layer causes the layer to collapse completely. A collapsed div is basically invisible, hard to style and generally a source of confusion.

Adding the knob

In the HTML, activate the knobs div by removing the comment around it. Also add a CSS class that positions the knobs div within it’s positioned parent.

/* styles the div that is inserted below the input checkbox html element */
.knobs
{
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
}

Style the two states checked and unchecked of the knobs div.

#button-1 .knobs:before
{
content: 'NO';
position: absolute;
top: 4px;
left: 4px;
width: 20px;
height: 10px;
color: #fff;
font-size: 10px;
font-weight: bold;
text-align: center;
line-height: 1;
padding: 9px 4px;
/*background-color: #03A9F4;*/
background-color: #f44336;
border-radius: 50%;
transition: 0.3s cubic-bezier(0.18, 0.89, 0.35, 1.15) all;
}

/* Style for when the checkbox is checked */
#button-1 .checkbox:checked + .knobs:before
{
content: 'YES';
left: 42px;
background-color: #03A9F4;
/*background-color: #f44336;*/
}

The CSS selector above contains .checkbox:checked which is how the checkbox state is targeted using CSS. The first of the two states does not contain any state so this is the default unchecked state. A transition is contained in the first CSS class. The transition defines how the transition between both CSS classes is animated. This animation moves the knob from left to right and vice versa, it changes the text and the color.

Adding the Layer

To also style the layer, first uncomment the layer div in the HTML. Then, using the same principle as for the knobs, define two CSS classes one per checkbox state that define the appearance of the layer in each state and how the transition between the two states is animated.

/* The layer is the background that the slider knob is displayed inside.
It is inserted as a separate div below the input checkbox html element
The layer provides the visual appearance and the outline border around the ckeckbox. */
.layer
{
--dummy-style: foo; /**/
position: absolute;
border-radius: 100px;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
background-color: #fcebeb;
/*background-color: #ebf7fc;*/
/*background-color: #f44336;*/
transition: 0.3s ease all;
z-index: 1;
}

/**
The general sibling combinator is made of the "tilde" (U+007E, ~)
character that separates two sequences of simple selectors.
The elements represented by the two sequences share the same parent in the document tree
and the element represented by the first sequence precedes (not necessarily immediately)
the element represented by the second one.
*/
#button-1 .checkbox:checked ~ .layer
{
/*background-color: #fcebeb;*/
background-color: #ebf7fc;
/*background-color: #03A9F4;*/
}

#button-1 .knobs, #button-1 .knobs:before, #button-1 .layer
{
transition: 0.3s ease all;
}

Summary and Next Steps

The toggle works and looks awesome. Things that come to mind are, how to you get translated text onto the toggle? Maybe it is easier to not have any text on the knob of the toggle to save a lot of work. Also the CSS probably should be translated to SCSS if that is what your project uses. Another important part is to use the toggle in a form element of your framework of choice. A test has to be made if the input works nicely with Angular, Vue and React.