Crafting UI

Tips & Tricks

Agenda

Custom properties

Pseudo-elementer

Scroll-teknikker

Math-funktioner

Custom properties

Pseudo-elementer

Scroll-teknikker

Math-funktioner

Agenda

Målet for i dag

  1. Få mere ud af Custom properties

  2. Anvende Pseudo-elementer til at underbygge UI

  3. Forstå, hvordan Scroll-teknikker hjælper med UX

  4. Vide, hvordan Math-funktioner kan hjælpe med layout

Custom properties

Pseudo-elementer

Scroll-teknikker

Agenda

Målet for i dag

  1. Få mere ud af Custom properties

  2. Anvende Pseudo-elementer til at underbygge UI

  3. Forstå, hvordan Scroll-teknikker hjælper med UX

  4. Vide, hvordan Math-funktioner kan hjælpe med layout

Math-funktioner

Custom Properties

Mål: Få mere ud af dem

Custom Properties

html {
  --primary: #5000ca;
  --secondary: #463866;
  --accent: #fb28a8;

  --space-xxs: 0.25rem;
  --space-xs: 0.5rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2rem;
  --space-xl: 3rem;
  --space-xxl: 6rem;
}

eksempel

"Consistency"

Custom Properties

html {
  --space-sm: 1rlh;
  --space-lg: 2rlh;
}

.flow {
  > * + * {
    margin-top: var(--flow-space, var(--space-sm));
  }
  
  h2 {
    --flow-space: var(--space-lg);
  }
}

Flow-space

The cascade

p {
  color: green;
}

#context {
  color: red;
}
<div id="context">
  <p>Some text</p>
</div>

Custom Properties

The cascade

Quiz

specificity & inheritance

#test p {
  color: blue;
}

p:hover {
  color: red;
}
<div id="test">
  <p>Lorem, ipsum dolor.</p>
</div>

Quiz

specificity & inheritance

#test p {
  color: var(--c, blue);
}

p:hover {
  --c: red;
}
<div id="test">
  <p>Lorem, ipsum dolor.</p>
</div>

Quiz

specificity & inheritance

p {
  color: var(--c);
}

#test {
  --c: blue;
}

p:hover {
  --c: red;
}
<div id="test">
  <p>Lorem, ipsum dolor.</p>
</div>
var(--value, 10px)

Custom Properties

Default værdi

.grid {
  display: grid;
  grid-template-columns:
    repeat(var(--cols, 3), 1fr);
}

@media (width > 40em) {
  .grid {
    --cols: 5;
  }
}

Custom Properties

Default værdi

:root {
  --my-color: green;
}

aside {
  --my-color: red;
}

p {
  color: var(--my-color);
}
aside p {
  --my-color: red;
}

p {
  color: var(--my-color, green);
}

Custom Properties

:root {
  --my-color: green;
}

aside {
  --my-color: red;
}

p {
  color: var(--my-color);
}
aside {
  --my-color: red;
}

p {
  color: var(--my-color, green);
}

Custom Properties

Tema-opgaven

øvelse

Themed sections

Brug custom properties til lettere at organisere hver sektions farvetema

[data-surface="primary"] {
  --bg-section: #eee;
  --bg-card: #fff;
}

Tema-opgaven

Custom Properties

SVG through data URL

:root {
	--svg: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">[SVG PATH]</svg>');
}

Custom Properties

pass-through colors in SVG

<!-- icons.svg -->
<svg>
  <symbol id="signal" viewBox="0 0 100 100">
    <path fill="#324D5B" d="..."></path>
  </symbol>
</svg>
<!-- HTML file -->
<svg width="100" height="100">
  <use href="icons.svg#signal" style="--sky: blue">
</svg>

Custom Properties

pass-through colors in SVG

<!-- icons.svg -->
<svg>
  <symbol id="signal" viewBox="0 0 100 100">
    <path fill="var(--sky, #324D5B)" d="..."></path>
  </symbol>
</svg>
<!-- HTML file -->
<svg width="100" height="100">
  <use href="icons.svg#signal" style="--sky: blue">
</svg>

Custom Properties

pass-through colors in SVG

<!-- icons.svg -->
<svg>
  <symbol id="signal" viewBox="0 0 100 100">
    <path fill="var(--sky, #324D5B)" d="..."></path>
  </symbol>
</svg>
<!-- HTML file -->
<svg width="100" height="100">
  <use href="icons.svg#signal" style="--sky: blue">
</svg>

Custom Properties

* {
  --repeat: repeat(auto-fit, minmax(var(--min-repeat), 1fr));
}

.grid {
  --min-repeat: 250px;
  grid-template-columns: var(--repeat);
}

figure {
  --min-repeat: 100px;
  grid-template-columns: var(--repeat);
}

Custom Properties

Color Management

Loading...

Custom Properties

dry

Loading...

Custom Properties

dry

Loading...

Custom Properties

Custom Properties

Boolean-ish

.rotate {
  --intent: 0;
  
  opacity: var(--intent);
  
  &:hover {
    --intent: 1;
  }
}

Mål: Anvende dem til at underbygge UI

Pseudo-elementer

Pseudo-elementer

::before, ::after

a::after {
  content: '(opens in new tab)';
}

Pseudo-elementer

::before, ::after

a[href^="http"]::after {
  content: '(opens in new tab)';
}

Pseudo-elementer

::before, ::after

a[href^="http"]::after {
  content: '(opens in new tab)';
}

Pseudo-elementer

Øvelse

nav.innerHTML += `<a href=${c.link}>${c.name}</a>` + " / ";

Pseudo-elementer

Øvelse

nav.innerHTML += `<a href=${c.link}>${c.name}</a>` + " / ";

Pseudo-elementer

Øvelse

li + li::before {
  content: '/';
}

Pseudo-elementer

Øvelse

content: open-quote;

Pseudo-elementer

Pseudo-elementer

Øvelse

Pseudo-elementer

Øvelse

Pseudo-elementer

content: attr(data-tooltip);
<span data-tooltip="I'm a tooltip">
  vero
</span>

Pseudo-elementer

Scroll-teknikker

Mål: Forstå, hvordan de hjælper med UX

sticky position, scroll snap

Sticky

øvelse

Position sticky

Lad overskrifter følge med ved scroll

UI Challenge

Sticky Labels

øvelse

Scroll Snap

Lad sektionerne finde sig til rette i viewporten ved at definere snap points

html {
  scroll-snap-type: y mandatory;
}

section {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

øvelse

Scroll Snap

Lad sektionerne finde sig til rette i viewporten ved at definere snap points

html {
  scroll-snap-type: x mandatory;
}

body {
  display: flex;
  overflow-x: auto;
  
  > * {
    flex: 1 0 70%;
  }
}

section {
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

Math-funktioner

Mål: Vide, hvordan de kan hjælpe med layout

calc()

min()

max()

clamp()

calc(

)

100px * 2

calc(

)

100px * 2

calc(

)

100% - 1rem

.card {
  padding: 1rem;
  border-radius: calc(1.75rem + 1rem);
  
  .inner {
    border-radius: 1.75rem;
  }
}
:root {
  --size: 20;
}

.box {
  width: var(--size)px;
}

eller fra JS

:root {
  --size: 20;
}

.box {
  width: var(--size) px;
  width: var(--size)px;
  width: var(--size)+px;
}

Ingen konkatenering

:root {
  --size: 20;
}

.box {
  width: calc(var(--size) * 1px); /* 20 * 1px = 20px */
}

calc()

calc()-pattern

calc()

Custom Properties

Boolean-ish øvelse

.rotate {
  --intent: 0;
  
  rotate: /* rotér v/ hover */ ;
  
  &:hover {
    --intent: 1;
  }
}

Brug calc() til at gange variablen med 45deg

0 * 45deg = 0deg

1 * 45deg = 45deg

øvelse

Linear Mapping

Brug lineær mapping til at animere en variabel font ved musens bevægelse

.element {
  --range: calc(0.6em * var(--p) + 0.2em);
  /*
  If --p is 0 --range is .2em
  If --p is 1 --range .8em
  */
}

min(

)

100px, 200px

min(

)

Brug den mindste værdi

100px, 200px

🤷‍♂️

min(

)

100px, 200px

🤔

100%, 200px

Brug den mindste værdi

Browseren omregner altid til px

.container {
  width: min(100%, 200px);
  
  /*
   width: 100%;
   max-width: 200px;
  */
}

min()

.container {
  width: min(100% - 2rem, 200px);
  
  /*
   width: calc(100% - 2rem);
   max-width: 200px;
  */
}

min()

65ch

3rem

.container {
  max-width: 65ch;
  margin-inline: 1rem;
  padding: .5rem;
  
  @media (width > 600px) {
  	padding: 3rem;
  	margin-inline: auto;
  }
}

auto

auto

.container {
  max-width: 65ch;
  margin-inline: 1rem;
  padding: .5rem;
  
  @media (width > 600px) {
  	padding: 3rem;
  	margin-inline: auto;
  }
}

< 100%

.container {  
  padding: min(3rem, 5%);
  width: min(65ch, 100% - 2rem);
  margin-inline: auto;
}

min()-pattern

min()

Kan typisk bruges til padding, margin og gap

Prøv selv

Indholdsbredden

overflow

main {  
  display: grid;
  grid-template-columns:
    1fr minmax(0, 1200px) 1fr;
  
  > * {
    grid-column: 2;
  }
  
  .full {
    grid-column: 1 / -1;
  }
}

1fr

1fr

minmax(0, 1200px)

main {  
  display: grid;
  grid-template-columns:
    1fr minmax(0, 1200px) 1fr;
  ...
}



.scroller {
  padding-inline:
    max(1rem, 50% - 1200px / 2);
}
:root {
  --content-width: 75rem;
}

main {
  grid-template-columns:
    1fr minmax(0, var(--content-width)) 1fr;
}

.scroller {
  padding-inline:
    max(1rem, 50% - var(--content-width) / 2);
}

max()-pattern

max()-pattern

max()

max(

)

1rem, min(50%, 400px)

Sæt grænser i hver ende

😵‍💫

clamp(

clamp(

)

1rem, 50%, 400px

Sæt grænser i hver ende

max(

calc(), min(), max()

Math patterns

.container {
  height: calc(100% - 2rem);
  /* --- */
  width: calc(var(--number) * 1px);
  /* --- */
  width: min(65ch, 100% - 2rem);
  /* --- */
  padding: max(1rem, 50% - 1200px / 2);
}

øvelse

Scrolling Container

Lav øvelsen, der ligger på git-branch'en "scrolling-container" på GitHub

Crafting UI: Tips & Tricks

By Dannie Vinther

Crafting UI: Tips & Tricks

  • 181