CRAFTING UI
Frontend Design
Custom properties, style queries & custom commands
Forstå bedre
Forstå, hvordan man opbygger robuste layouts med
Kan -funktioner hjælpe med layout?
Øvelser for at opbygge praktisk erfaring
--brand og --card-padding.:hover. --_ er kun en navnekonvention.hsl()-farver eller en størrelse i calc()..card {
padding: 1rem;
@container (width > 30ch) {
padding: 2rem;
}
}Smart?
.card {
padding: 1rem;
@container (width > 30ch) {
padding: 2rem;
}
h2 {
font-size: 1.5rem;
@container (width > 30ch) {
font-size: 2.5rem;
}
}
.card-actions {
@container (width > 30ch) {
flex-direction: row;
}
}
}Er det en god ide?
.card {
padding: 1rem;
h2 {
font-size: 1.5rem;
}
@container (width > 30ch) {
.card {
padding: 2rem;
}
h2 {
font-size: 2.5rem;
}
.card-actions {
flex-direction: row;
}
}
}Er det en god ide?
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;
}html {
--space-sm: 1rlh; /* eller flydende */
--space-lg: 2rlh; /* eller flydende */
}
.flow {
> * + * {
margin-top: var(--flow-space, var(--space-sm));
}
h2 {
--flow-space: var(--space-lg);
}
}var(--value, 10px).grid {
display: grid;
grid-template-columns:
repeat(var(--cols, 3), 1fr);
}
@media (width > 40em) {
.grid {
--cols: 5;
}
}.object-1 {
--move-to: 100px;
}
.object-2 {
--move-to: 400px;
}
[class|="object"] {
animation: move 1s linear forwards;
}
@keyframes move {
to {
translate: var(--move-to);
}
}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>');
}
Boolean-ish
.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
Boolean-ish
.slide-out {
--open: 0;
opacity: var(--open);
translate: calc( var(--open) * 100% );
transition:
opacity .4s,
translate .4s;
&.open {
--open: 1;
}
}Brug calc() til at gange variablen med 100%
Boolean-ish
.element {
--range: calc(0.6em * var(--p) + 0.2em);
/*
If --p is 0 --range is .2em
If --p is 1 --range .8em
*/
}Brug lineær mapping til at animere en variabel font ved musens bevægelse
Øvelse
p {
color: green;
}
#context {
color: red;
}<div id="context">
<p>Some text</p>
</div>:root {
--my-color: green;
}
aside {
--my-color: red;
}
p {
color: var(--my-color);
}aside p {
--my-color: red;
}
p {
color: var(--my-color, green);
}:root {
--my-color: green;
}
aside {
--my-color: red;
}
p {
color: var(--my-color);
}aside {
--my-color: red;
}
p {
color: var(--my-color, green);
}@container
Spørg containeren
@container
Spørg containeren
Tema-opgaven
[data-surface] {
--surface: attr(data-surface type(dark | light));
}
[data-surface="dark"] {
--surface-bg: var(--color-neutral-900);
}
.card {
--card-bg: var(--color-neutral-700);
@container style(--surface: dark) {
--card-bg: var(--color-neutral-100);
}
}<section data-surface="dark">
<!-- content -->
</section>style queries
[data-surface] {
--surface: attr(data-surface type(dark | light));
}
[data-surface="dark"] {
--surface-bg: var(--color-neutral-900);
}
.card {
--card-bg: var(--color-neutral-700);
@container style(--surface: dark) {
--card-bg: var(--color-neutral-100);
}
}<section data-surface="dark">
<!-- content -->
</section>style queries
Brug custom properties og style queries til lettere at organisere hver sektions farvetema samt indhold.
Øvelse
Lav øvelsen, der ligger på git-branch'en "scrolling-container" på GitHub
Øvelse
Opskrift:
.scroll-container {
scroll-snap-type: inline mandatory; /* block, proximity */
overflow-inline: auto; /* scroll */
}
.item {
scroll-snap-align: center; /* start, end */
}Demo
Deklarativ interaktion
<button
command="toggle-popover"
commandfor="popover-1">
Open Popover
</button>
<div popover id="popover-1">
<!-- indhold -->
</div>
Custom commands
Custom commands
Custom commands
Custom commands
const scroller = document.querySelector("#scroller");
scroller.addEventListener("command", (e) => {
if (e.command === "--scroll") {
scroller.scrollBy({
left: scroller.offsetWidth * e.source.value
})
}
});<button
value="-.9"
command="--scroll"
commandfor="scroller">
Prev
</button>Custom commands
const scroller = document.querySelector("#scroller");
scroller.addEventListener("command", (e) => {
if (e.command === "--scroll") {
scroller.scrollBy({
left: scroller.offsetWidth * e.source.value
})
}
});<button
value="-.9"
command="--scroll"
commandfor="scroller">
Prev
</button>disabled
function disableButtons() {
const maxScroll = scroller.scrollWidth - scroller.offsetWidth;
prev.disabled = scroller.scrollLeft <= 0;
next.disabled = scroller.scrollLeft >= maxScroll - 1;
}
scroller.addEventListener("scroll", disableButtons);
disableButtons()Hele bredden
Den synlige bredde
boolean
boolean
pattern
: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);
}pattern
section {
padding-inline:
max(1rem, 50% - var(--content-width) / 2);
}Lav øvelsen, der ligger på git-branch'en "scrolling-container" på GitHub
Øvelse
NB! Du skal selv sætte knapperne ind