Crafting UI
Datavisualisering (CSS og SVG)
Datavisualisering

Datavisualisering
Det handler ikke kun om at vise data men om at designe den måde, data forstås på.
- gør kompleks data læsbar, sammenlignelig og handlingsbar
- fremhæver mønstre, relationer og afvigelser
- fører (måske) til øget engagement
Fra temaopgaven
Procentcirkler

Datavisualisering
CSS
SVG
Vores værktøjkasse
attr()
mm.
shape()
Gradienter
offset-path
<path>
<circle>
pathLength
stroke-dasharray
stroke-dashoffset
border-area
Pseudo-elementer
a::after {
content: '(opens in new tab)';
}Pseudo-elementer
::before, ::after
a[href^="http"]::after {
content: '(opens in new tab)';
}
Pseudo-elementer
::before, ::after
Pseudo-elementer
::before, ::after
a[href^="http"]::after {
content: '(opens in new tab)';
}
Øvelse
nav.innerHTML += `<a href=${c.link}>${c.name}</a>` + " / ";
Pseudo-elementer
Øvelse
Pseudo-elementer
Øvelse
nav.innerHTML += `<a href=${c.link}>${c.name}</a>` + " / ";
Pseudo-elementer
Øvelse
li + li::before {
content: '/';
}
Pseudo-elementer
Øvelse
li + li::before {
content: '/';
}
Pseudo-elementer
li:has(a)::after {
content: '/';
}li:has(+ li)::after {
content: '/';
}li:not(:last-child)::after {
content: '/';
}:not(:first-child)::before {
content: '/';
}Pseudo-elementer
Fra Temaopgaven
Pseudo-elementer

Øvelse
Pseudo-elementer
Øvelse

Pseudo-elementer

Tegn med gradienter
Koniske, lineære, radiale
Tegn med gradienter
Koniske, lineære, radiale
Conic-gradient()
Procentcirkel (doughnut)
Offset-path
Offset-path
.parent {
.child {
offset-path: border-box;
}
}Offset-path
10%20%30%40%50%60%70%100%<article>
<div></div>
</article>article {
display: grid;
grid-template-columns:
repeat(8, 1fr);
height: 300px;
}
div:nth-child(1) {
height: 100%;
}
div:nth-child(2) {
height: 70%;
}
...<article>
<div></div>
<div></div>
...
</article>Ikke så fleksibelt
10%20%30%40%50%60%70%100%article {
display: grid;
grid-template-columns:
repeat(8, 1fr);
}
div:nth-child(1) {
height: 100%;
}
div:nth-child(2) {
height: 70%;
}
...<article>
<div style="height: 100%"></div>
<div style="height: 70%"></div>
...
</article>Data kommer typisk fra JS
10%20%30%40%50%60%70%100%bar.style.height = `${percent}%`div {
height: var(--height, 0%);
}<article>
<div style="--height: 100%"></div>
<div style="--height: 70%"></div>
...
</article>Det kunne ligeså godt se sådan ud
10%20%30%40%50%60%70%100%bar.style.setProperty("--height", `${percent}%`)<article>
<div data-percent="100"></div>
<div data-percent="70"></div>
...
</article>Eller sådan her
(en moderne løsning)
div {
height: attr(data-percent %), 0%);
}10%20%30%40%50%60%70%100%bar.dataset.percent = `${percent}%`attr()
div {
width: attr(data-length type(<length>));
&::after {
content: attr(data-length);
}
}attr(data-number type(<number>), 0)
<div data-length="5rem"></div>attr()
Hent og brug værdier fra attributter
div {
width: attr(data-length type(<length>));
&::after {
content: attr(data-length);
}
}attr()
Units vs. Types
attr()
Types of type()
<angle>
<color>
<custom-ident>
<image>
<integer>
<length>
<length-percentage>
<number>
<percentage>
<time>
attr()
og calc()
div {
height: attr(data-percent %), 0%);
}

Lad os bygge en
responsiv Bar Chart
.bars {
display: grid;
grid-template-columns: repeat(8, 1fr);
height: 300px;
}Step 1: Orientering
Basic grid
<article class="bars">
<div class="bar" data-percent="100"></div>
<div class="bar" data-percent="70"></div>
<!-- ... -->.bar {
height: attr(data-percent %); /* 70% */
}Step 2: attr()
Sæt højden i %
<article class="bars">
<div class="bar" data-percent="100"></div>
<div class="bar" data-percent="70"></div>
<!-- ... -->
.bar {
height: attr(data-percent %, 0%); /* 0% */
}Step 2: attr()
Husk fallback!
<article class="bars">
<div class="bar" data-percent="100"></div>
<div class="bar"></div>
<!-- ... -->.bar {
background:
color-mix(#3980DD attr(data-percent %, 0%), #DAE9FC);
}Step 3: color-mix()
Procent-værdien styrer baggrundsfarven

.bar {
--percent: attr(data-percent %, 0%);
background:
color-mix(#3980DD var(--percent), #DAE9FC);
height: var(--percent);
}Step 4: Housekeeping
Organiser med variabler

.bar {
&::after {
content: attr(data-percent) "%";
position: absolute;
top: -1lh;
inset-inline: 0;
justify-self: center;
}
}Step 5: pseudo-element
Vis procent-værdien


.bar {
&::after {
content: attr(data-percent) "%";
position: absolute;
top: -1lh;
inset-inline: 0;
justify-self: center;
}
}Step 5: pseudo-element
Vis procent-værdien


.bars {
@container (width < 400px) {
writing-mode: sideways-rl;
height: 100%;
}
}
.bar {
min-width: 40px;
}Step 6: writing-mode
Gør den responsiv


writing-mode
div {
width: attr(data-length type(<length>));
&::after {
content: attr(data-length);
}
}writing-mode: sideways-lr | sideways-rl etc.
writing-mode
med flow-relative properties
writing-mode
med flow-relative properties

width
max-width
height
max-height
margin-left
margin-right
padding-top
top
inline-size
max-inline-size
block-size
max-block-size
margin-inline-start
margin-inline-end
padding-block-start
inset-block-start
writing-mode
med flow-relative properties
.bars {
@container (width < 400px) {
writing-mode: sideways-rl;
height: 100%;
}
}
.bar {
min-width: 40px;
}Step 6: writing-mode
Gør den responsiv


.bars {
block-size: 300px; /* erstatter height */
@container (width < 400px) {
writing-mode: sideways-rl;
block-size: 100%; /* erstatter height */
}
}
.bar {
min-inline-size: 40px; /* erstatter min-width */
&::after {
inset-block-start: -1lh; /* erstatter top */
}
}Step 7: Logical props
Gør boksmodellen flow-relativ


.bars {
@container (width < calc((40px + 1rlh) * 8)) {
/* ... */
}
}
.bar {
margin-inline: .5rlh;
min-inline-size: 40px;
}Tip
Brug calc() i @container


bar width
.bars {
background:
repeating-linear-gradient(
to bottom,
gainsboro 0 1px,
transparent 0 25%
);
}Step 8: Gitterlinjer
Linjer med repeating-gradient


.bars {
background:
repeating-linear-gradient(
var(--angle, to bottom),
gainsboro 0 1px,
transparent 0 25%
);
}Step 8: Gitterlinjer
Fix linjer på små skærme


.bars {
background:
repeating-linear-gradient(
var(--angle, to bottom),
gainsboro 0 1px,
transparent 0 25%
);
@container (inline-size < 400px) {
--angle: to left;
}
}Step 8: Gitterlinjer
Fix linjer ved breakpointet


Hvordan virker det?
.bars {
background:
repeating-linear-gradient(
to bottom,
gainsboro 0 1px,
transparent 0 25%
);
}to bottom
0
1px
25%
(180deg)
Crafting UI: Datavisualisering
By Dannie Vinther
Crafting UI: Datavisualisering
Crafting UI – Datavisualisering
- 72