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
-
Få mere ud af Custom properties
-
Anvende Pseudo-elementer til at underbygge UI
-
Forstå, hvordan Scroll-teknikker hjælper med UX
-
Vide, hvordan Math-funktioner kan hjælpe med layout
Custom properties
Pseudo-elementer
Scroll-teknikker
Agenda
Målet for i dag
-
Få mere ud af Custom properties
-
Anvende Pseudo-elementer til at underbygge UI
-
Forstå, hvordan Scroll-teknikker hjælper med UX
-
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