- let num = 4, ang = 90, cx = 50, cy = 50, col = '#9c82da';
body(style=`--num: ${num}; --ang: ${ang}deg; --cx: ${cx}%; --cy: ${cy}%; --col: ${col}`)
svg(width='0' height='0' aria-hidden='true')
filter#grad-xor(color-interpolation-filters='sRGB')
feColorMatrix(values=`0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0` result='mode')
feColorMatrix(in='SourceGraphic'
values=`0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0` result='xbck')
feColorMatrix(in='SourceGraphic'
values=`0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0` result='xgrd')
feFlood(flood-color='var(--grad-0)')
feComposite(in2='xgrd' operator='in'
result='basexgrd')
feFlood(flood-color='var(--link-0)')
feComposite(in2='xbck' operator='in')
feBlend(in='basexgrd' result='base_xor')
feFlood(flood-color='var(--xtra-0)')
feComposite(in2='xbck' operator='in')
feBlend(in='base_xor')
feComposite(in2='mode' operator='out'
result='basemode')
feFlood(flood-color='var(--grad-1)')
feComposite(in2='xgrd' operator='in'
result='darkxgrd')
feFlood(flood-color='var(--link-1)')
feComposite(in2='xbck' operator='in')
feBlend(in='darkxgrd' result='dark_xor')
feFlood(flood-color='var(--xtra-1)')
feComposite(in2='xbck' operator='in')
feBlend(in='dark_xor')
feComposite(in2='mode' operator='in')
feBlend(in='basemode')
feComposite(in2='SourceAlpha' operator='in')
header: h1 I am a heading contrasting with the background
main
section
time(datetime='2022-10-19') 19th of October 2022
p Sadly,
a(href='https://www.patreon.com/anatudor' target='_blank') links
| here need to be made either
code inline-block
| and use absolutely positioned pseudos that fully cover them or have their text content wrapped in a
code span
| if we want
a.deco(href='https://ko-fi.com/anatudor' target='_blank') underlines
| .
p This is due to a Firefox
a.fxor(href='https://bugzilla.mozilla.org/show_bug.cgi?id=1481498' target='_blank') bug
| old enough to go to school. Note this link has a XOR effect on
code :hover
| /
code :focus
| , which, due to the way the swipe effect works, requires an SVG
code filter
| ... which
em could have been simpler
|
strong if
| browsers were consistent!
p Both the
code inline-block
| method and the extra
code span
| one have their disadvantages.
p But going from a plain XOR effect to a
a.grad(href='#') gradient
| one is straightforward - we replace the solid
code background
| with a gradient, also clipped to
code text
| (then inherited by a pseudo creating the underline that grows to a full coverage rectangle XOR-ed with the text on
code :hover
| /
code :focus
| ).
p It's the same situation for most other elements that need to have both their text and
i background
| /
b border
| /
u decoration
| change from one theme to the other.
p Text looking as if
mark: span highlighted
| with a marker, for example. In theory, it's
del super
ins reasonably
| easy to do without pseudos or nested spans. In practice, Firefox says
q(cite='https://bugzilla.mozilla.org/show_bug.cgi?id=1481498') can't do that
| . It doesn't scream to say
samp Error
| , but you get the idea.
p Or buttons! Plain buttons need the nested
code span
| approach if we don't want to bother with SVG filters.
button: span button
p Gradient buttons require an SVG
code filter
| anyway (as anything with gradients does for a this kind of swipe theme switch), so we can do without any kind of nesting here.
button.grad gradient button
p We can also create buttons using
code input[type=button]
| . Since we cannot have any kind of nesting in this case, we take the SVG
code filter
| approach.
input(type='button' value='[type=button]')
input.grad(type='button' value='[type=button]')
p Now the page heading was a special one interacting with its backdrop.
h2 A normal heading
h3 Lists
h4 Unordered list
ul
li Leopard
li Jaguar
li Lion
li Tiger
h4 Ordered list
ol
li Leopard
li Jaguar
li Lion
li Tiger
h4 Description list
dl
dt Tiger (
i Panthera tigris
| )
dd A member of the genus
b Panthera
| and the largest living cat species.
dt Snow leopard (
i Panthera uncia
| )
dd A species of large cat in the genus
b Panthera
| of the family
b Felidae
| .
h3 Some other things you may find on a page
//figure
img(src='https://images.unsplash.com/photo-1603123495144-59fa702e8dd0?&w=400' alt='tiger')
figcaption tiger
//p Let's try another image, this time with a gradient border.
//figure.grad
img(src='https://images.unsplash.com/photo-1603123495144-59fa702e8dd0?&w=400' alt='tiger')
figcaption tiger
//video(src='https://i.imgur.com/8sOjFCw.mp4' controls)
blockquote
p We bring the people of the world together so you can watch them tear each other apart.
cite social media
hr
p The basic
abbr(title='Cascading Style Sheets') CSS
| idea in this demo is the following:
pre(data-lang='CSS')
code
| body { --dark: 0 }
| body:has(#dark:checked) { --dark: 1 }
p Then we use
code --dark
| inside animated gradients to produce this effect. You may find out more via
kbd Ctrl + Shift + C
| .
p Some stuff I code may be a bit Mathy, so I need variables
var x
| and I may need need to use exponents
var e
sup x
| . I've been toying with
dfn: attr(title='Scalable Vector Graphics') SVG
| lately, so that's a lot of playing with input
var R
sub i
| and output channels.
// Speaking of mathy stuff...
//math
mi c
mo =
msqrt
msup
mi a
mn 2
mo +
msup
mi b
mn 2
aside.theme-controls
h2 Swipe effect controls
form
fieldset
legend Type of swipe
.wrap
input#lin(type='radio' name='typ' checked)
label(for='lin') linear
input#rad(type='radio' name='typ')
label(for='rad') radial
input#con(type='radio' name='typ')
label(for='con') conic
//.wrap
input#rep(type='checkbox')
label(for='rep') repeating
.wrap.wrap--1x(style=`--max: 360`)
label(for='ang') Angle
.cont
input#ang(type='range' value=ang max='360'
style=`--unit: deg`)
output(for='ang' style=`--unit: '°'; --val: ${ang}`) #{ang}
fieldset#pos(style=`--unit: %`)
legend Position
.wrap
.wrap.wrap--1x(style=`--max: 100`)
label(for='cx') x
.cont
input#cx(type='range' min='0' value=cx max='100')
output(for='cx' style=`--unit: '%'; --val: ${cx}`) #{cx}
.wrap.wrap--1x(style=`--max: 100`)
label(for='cy') y
.cont
input#cy(type='range' min='0' value=cy max='100')
output(for='cy' style=`--unit: '%'; --val: ${cy}`) #{cy}
//.wrap
label(for='num') Repetitions
input#num(type='number' min='2' value=num max='20' required data-default=num)
output(for='num')
fieldset
legend Custom palette
.wrap
small You can't possibly expect me to let you to mess with more than this border...
.wrap
input#col(type='color' value=col)
output(for='col') #{col}
footer
aside.theme-switch
.wrap(role='group' aria-label='Theme')
input#auto(type='radio' name='theme' checked)
label(for='auto' data-ico='🖥️') auto
input#light(type='radio' name='theme')
label(for='light' data-ico='☀️') light
input#dark(type='radio' name='theme')
label(for='dark' data-ico='🌙') dark
View Compiled
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&family=Red+Hat+Mono:ital,wght@0,300..700;1,300..700&family=Grandstander:ital,wght@0,100..900;1,100..900&family=Oxanium:wght@200..800&family=REM:ital,wght@0,100..900;1,100..900&display=swap');
/* Palette #1 *
$back-0: #dbdce0; // light theme background
$back-1: #39393c; // dark theme background
$text-0: $back-1; // light theme text
$text-1: $back-0; // dark theme text
$link-0: #573cff; // light theme links+ sel toggles
$link-1: #00f1fd; // dark theme links+ sel toggles
$grad-0: #c50055;
$grad-1: #f67280;
/**/
/* Palette #2 *
$back-0: #ecf1f7; // light theme background
$back-1: #262c33; // dark theme background
$text-0: $back-1; // light theme text
$text-1: $back-0; // dark theme text
$link-0: #163289; // light theme links+ sel toggles
$link-1: #9fe7c1; // dark theme links+ sel toggles
$grad-0: #8f4f09;
$grad-1: #f9c039;
/**/
/* Palette #3 */
$back-0: #e8e8e8; // light theme background
$back-1: #2b2b2f; // dark theme background
$text-0: $back-1; // light theme text
$text-1: $back-0; // dark theme text
$link-0: #006a6a; // light theme links+ sel toggles
$link-1: #adfffe; // dark theme links+ sel toggles
$grad-0: #79226a;
$grad-1: #ef88d5;
/**/
/* Palette #4 *
$back-0: #d9e0fd; // light theme background
$back-1: #041c40; // dark theme background
$text-0: $back-1; // light theme text
$text-1: $back-0; // dark theme text
$link-0: #610c78; // light theme links+ sel toggles
$link-1: #fbdcfc; // dark theme links+ sel toggles
$grad-0: #012f8d;
$grad-1: #b7cff9;
/**/
// other constants
$dots-s: 1em;
$main-w: min(100%, 65em);
$line-w: 2px;
$rect-r: 5px;
$s: .5em;
$t: .65s;
$track-h: 6px;
$track-r: .5*$track-h;
$thumb-d: 1em;
$thumb-r: .5*$thumb-d;
$thumb-o: -1*$thumb-r;
// mixins
@mixin thumb($f: 0) {
@if $f == 0 { border: none }
width: $thumb-d; height: $thumb-d;
border-radius: 50%;
background: var(--func) fixed;
cursor: ew-resize
}
/* ====== CSS vars declarations ====== */
@property --perc-ani {
syntax: '<length-percentage>';
initial-value: 0px;
inherits: true
}
@property --hov {
syntax: '<number>';
initial-value: 0;
inherits: true
}
@property --sel {
syntax: '<number>';
initial-value: 0;
inherits: true
}
/* ====== GENERIC COMPONENTS ====== */
* {
margin: 0;
padding: 0;
background: none;
color: inherit;
font: inherit
}
*, ::before {
--c0:
color-mix(in srgb,
var(--comp-1) var(--perc-fix),
var(--comp-0));
--c1:
color-mix(in srgb,
var(--comp-1),
var(--comp-0) var(--perc-fix))
}
::after {
--c0: rgb(0%, var(--perc-fix), 0%);
--c1: rgb(0%, calc(100% - var(--perc-fix)), 0%)
}
/* ------ big page components ------ */
html, body, header, dl, aside, form, fieldset { display: grid }
html { min-height: 100% }
body {
/* initial case: light theme case, --dark is 0 */
--dark: 0;
/* Chrome stable without Experimental Web Platform
* features flag still needs this fallback */
--sign: calc(2*var(--dark) - 1);
/* changes instantly between 0% & 100% and back */
--perc-fix: calc(var(--dark)*100%);
/* smoothly animates between 0% & 100% and back */
--perc-ani: calc(var(--dark)*100%);
/* swipe gradient position, always from 0% to 100%,
* whether switch is from light to dark or not */
--perc:
calc(100% - var(--perc-fix) +
var(--sign)*var(--perc-ani));
--xtra-0: #{lighten($back-0, 5%)};
--xtra-1: #{darken($back-1, 5%)};
--text-0: #{$text-0};
--text-1: #{$text-1};
--link-0: #{$link-0};
--link-1: #{$link-1};
--grad-0: #{$grad-0};
--grad-1: #{$grad-1};
/* the two body background options we go between
* during a swipe (buggy in Epiphany) */
--comp-0: #{$back-0};
--comp-1: #{$back-1};
--grad:
linear-gradient(to right top, #00f, #f00);
--full: linear-gradient(red 0 0);
grid-template-rows:
repeat(2, max-content) 1fr max-content;
background:
radial-gradient($line-w,
hsla(0, 0%, 100%, .1) calc(100% - 1px), transparent)
0/ #{$dots-s $dots-s},
var(--func) fixed;
background-blend-mode: difference;
font: 300
Round(clamp(1em, 1.5vw + .5vh, 1.5em), 4px)/ 1.25
rem, sans-serif;
transition: --perc-ani $t ease-out;
/* wish we had functions so we didn't have to
* resort to this abomination */
&, & *, & ::before, & ::after {
--args: var(--set, var(--ang), )
var(--c0) var(--p0, var(--perc)),
var(--c1) var(--p1, 0%);
--func: linear-gradient(var(--args));
}
/* if there's a dark theme preference,
* but we want to force the light theme */
&:has(#light:checked) { --dark: 0 }
/* cases in which we switch --dark to 1 */
/* if there's a dark theme preference */
@media (prefers-color-scheme: dark) { --dark: 1 }
/* if we select the dark theme option */
&:has(#dark:checked) { --dark: 1 }
/* repeating */
&:has(#rep:checked) {
--calc: var(--perc)/var(--num);
--p0: 0% calc(var(--calc));
--p1: 0% calc(100%/var(--num));
//&, & * { --edge-correct: var(--c1) 0px, }
}
/* linear AND repeating */
&:has(#lin:checked):has(#rep:checked) {
&, & *, & ::before, & ::after {
--func: repeating-linear-gradient(var(--args))
}
}
/* radial */
&:has(#rad:checked) {
--set: circle at var(--cx) var(--cy), ;
&, & *, & ::before, & ::after {
--func: radial-gradient(var(--args))
}
/* radial AND repeating */
&:has(#rep:checked) {
&, & *, & ::before, & ::after {
--func: repeating-radial-gradient(var(--args))
}
}
}
/* conic */
&:has(#con:checked) {
--set: from var(--ang) at var(--cx) var(--cy), ;
&, & *, & ::before, & ::after {
--func: conic-gradient(var(--args))
}
/* conic AND repeating */
&:has(#rep:checked) {
&, & *, & ::before, & ::after {
--func: repeating-conic-gradient(var(--args))
}
}
}
}
/* functionally the same as a style element,
* take it out of document flow */
svg[aria-hidden='true'] { position: fixed }
header, main, footer, section, aside, fieldset {
padding: $s
}
header, aside {
grid-gap: $s;
grid-template-columns: $main-w;
justify-content: center
}
header {
--c0: hsl(0, 0%, calc(100% - var(--perc-fix)));
--c1: hsl(0, 0%, var(--perc-fix));
justify-self: stretch;
background:
var(--func) fixed,
linear-gradient(45deg, $back-1 calc(50% - 5em),
$back-0 0 calc(50% + 5em), $back-1 0),
url(https://images.unsplash.com/photo-1635070041078-e363dbe005cb?w=2400)
50%/ cover $back-1;
background-blend-mode: difference, difference, multiply;
text-align: center
}
h1 {
place-self: center;
color: #fff;
font-size: 3em;
font-weight: 900;
line-height: Round(up, 1.25em, 1px);
text-wrap: balance;
mix-blend-mode: difference
}
main, footer {
box-sizing: border-box;
justify-self: center;
width: $main-w
}
main, label, li {
display: flex;
align-items: center;
gap: $s
}
main {
flex-wrap: wrap-reverse;
align-items: flex-end;
> * { border-radius: calc(#{$s} + #{$rect-r}) }
}
section, aside {
--comp-0: var(--xtra-0);
--comp-1: var(--xtra-1);
box-shadow: 2px 2px 5px
rgba(0, 0, 0, calc(.3 + var(--dark)*.5));
background: var(--func) fixed
}
section { flex: 3 3 21.75em }
aside {
box-sizing: border-box;
position: sticky;
z-index: 2;
top: 0
}
dl, form, fieldset { grid-gap: $s }
h2, h3, h4, time, p, a, button span, q, samp, legend, input, label, output, small, li, dl, figcaption, cite, pre code, sub, sup {
--comp-0: #{$text-0};
--comp-1: #{$text-1};
color: #0000;
background: var(--func) text fixed
}
h2, h3, h4, h5, h5 { padding: .5*$s 0 }
h2 { font-size: 2em }
h3 { font-size: 1.5em }
h4 { font-size: 1.25em }
h5 { font-size: 1.125em }
time {
font-size: calc(1em - 4px);
font-family: orbitron, sans-serif
}
p {
padding: $s 0;
isolation: isolate;
code {
padding: 0 $line-w;
background: rgba(grey, .1)
}
}
code, samp, output {
font-family: red hat mono, monospace;
font-weight: 500
}
b, strong { font-weight: 600 }
i, em { font-style: italic }
u { text-decoration: underline double grey }
mark {
&:has(span) {
--comp-0: var(--grad-1);
--comp-1: var(--grad-0);
padding: 0 $line-w;
background: #ed9831;
background: var(--func) fixed
}
span {
--comp-0: var(--text-0);
--comp-1: var(--text-1);
background: var(--func) text fixed
}
}
ul, ol, dl { margin: $s 0 }
ol { counter-reset: c }
ol li::before {
width: 1em;
text-align: right;
counter-increment: c;
content: counter(c) '.'
}
ul li::before {
box-sizing: border-box;
padding: $line-w;
width: $s; height: $s;
border-radius: 50%;
background: inherit;
background-clip: border-box;
mask: var(--full) content-box exclude,
var(--full) padding-box;
content: ''
}
dd, blockquote, pre {
padding: $s;
background: rgba(grey, .1)
}
dt { font-weight: 700 }
dd { margin: 0 0 0 $s }
blockquote { margin: $s 0 }
blockquote p { font-family: grandstander, serif }
cite {
display: block;
font-style: italic;
text-align: right
}
figure, img, video, embed, iframe { max-width: 100% }
sub, sup {
--off: Round(-.5em, 1px);
position: relative;
vertical-align: hanging;
font-size: Max(.5rem, .625em);
line-height: 1;
}
sup { top: var(--off) }
sub {
bottom: var(--off);
vertical-align: baseline
}
legend {
padding: 0 $s;
font-weight: 400
}
/* ------ text highlight components ------ */
a, samp, q, ins, del { font-weight: 400 }
del, ins {
display: inline-block;
background: var(--func) text fixed
}
:is(del, ins)::before { vertical-align: middle }
del {
--comp-0: var(--grad-0);
--comp-1: var(--grad-1);
position: relative;
&::before { content: '✘' }
&::after {
position: absolute;
inset: 50% 0 calc(50% - #{$line-w}) .75em;
background: inherit;
background-clip: border-box;
pointer-events: none;
content: ''
}
}
ins {
--comp-0: var(--link-0);
--comp-1: var(--link-1);
&::before { content: '✔' }
}
q {
--comp-0: #00287d;
--comp-1: #b6c4ff;
}
samp {
--comp-0: #895100;
--comp-1: #ffb86d;
}
/* ------ interactive components ------ */
:is(a, button, input, input + [for]) {
--hov: 0;
--sel: 0;
--perc-sel: calc(var(--sel)*100%);
transition: $t;
transition-property: --hov, --sel
}
:is(a, button, input, label):is(:hover, :focus),
input:is(:hover, :focus) + [for] { --hov: 1 }
:is(a, button, [type='button'], [type='range']):active,
:is([type='radio'], [type='checkbox']):checked,
:is([type='radio'], [type='checkbox']):checked + label {
--sel: 1
}
a {
--comp-0: #{$link-0};
--comp-1: #{$link-1};
text-decoration: none;
&[class] {
--y: calc(100% - #{$line-w});
display: inline-block;
position: relative;
padding: 0 $line-w;
background-clip: text;
&::before, &::after {
position: absolute;
inset: -1px 0;
pointer-events: none
}
&::before {
background: inherit;
background-clip: border-box;
clip-path:
inset(var(--dty, var(--y)) 0 0);
content: ''
}
}
}
button,
[type='button'], [type='range'], [type='color'],
input + label { cursor: pointer }
button, [type='button'] {
margin: $line-w;
border: none;
padding: $s 2*$s;
border-radius: 1lh;
font-weight: 400
}
button {
&:not([class]) {
&:has(span) {
--comp-0: var(--link-0);
--comp-1: var(--link-1);
background: var(--func) fixed
}
}
&[class] {
--c0: rgb(0%, var(--perc-fix), 0%);
--c1: rgb(0%, calc(100% - var(--perc-fix)), 0%);
--mode: , var(--func) fixed;
background-blend-mode: lighten;
color: #000
}
span {
--comp-0: var(--xtra-0);
--comp-1: var(--xtra-1)
}
}
input:not([name='theme']) + [for] {
filter: Saturate(calc(var(--sel) + var(--hov)))
}
[type='button'] {
--c0: rgb(100%, var(--perc-fix), 0%);
--c1: rgb(100%, calc(100% - var(--perc-fix)), 0%);
color: #000;
&:not([class]) {
background: var(--func) fixed;
filter: url(#grad-xor)
}
&[class] {
--mode: , var(--func) fixed;
background-blend-mode: lighten
}
}
:is([type='radio'], [type='checkbox']) {
position: absolute;
opacity: .001;
&:not([name='theme']) + label {
--comp-0: var(--link-0);
--comp-1: var(--link-1);
&::before {
box-sizing: border-box;
border: solid $line-w #0000;
padding: Max(#{$line-w}, Round(.2em, 1px));
width: 1lh;
aspect-ratio: 1;
background: var(--func) fixed;
mask:
linear-gradient(
rgba(0, 0, 0, var(--sel)) 0 0)
content-box exclude,
var(--full) padding-box exclude,
var(--full);
content: ''
}
}
}
[type='checkbox'] + label {
display: grid;
grid-auto-flow: column;
place-items: center;
&::before, &::after { grid-area: 1/ 1 }
&::after {
--c0: hsl(0, 0%, calc(100% - var(--perc-fix)));
--c1: hsl(0, 0%, var(--perc-fix));
z-index: 2;
opacity: var(--sel);
background: var(--func) text fixed;
content: '✔';
@supports (content: '✔'/ '') { content: '✔'/ '' }
}
}
[type='radio'] + label::before {
border-radius: 50%
}
[type='range'] {
&, &::-webkit-slider-thumb { appearance: none }
--comp-0: var(--link-0);
--comp-1: var(--link-1);
width: 100cqw;
height: $track-h;
border-radius: $track-r;
background: grey;
cursor: pointer;
&::-webkit-slider-thumb { @include thumb(1) }
&::-moz-range-thumb { @include thumb }
&::slider-thumb { @include thumb }
&, & + output { grid-area: 1/ 1 }
& + output {
--pos: calc(#{$thumb-r} + var(--val)/var(--max)*(100cqw - #{$thumb-d}) + -50%);
position: relative;
place-self: start;
border: solid $s #0000;
padding: $line-w;
min-width: 2em;
border-radius: calc(#{$s} + 2*#{$line-w});
transform-origin: 50% 100%;
translate: var(--pos) -100%;
scale: var(--hov);
background:
color-mix(in srgb, var(--link-1) var(--perc-ani), var(--link-0));
color:
color-mix(in srgb, var(--xtra-1) var(--perc-ani), var(--xtra-0));
font-size: .8em;
text-align: center;
mask: var(--full) padding-box,
conic-gradient(from -45deg at 50% 100%,
red 25%, #0000 0)
50% 100%/ 50% 50% no-repeat border-box
}
}
[type='number'] {
border: solid $line-w grey;
padding: 0 $s;
border-radius: 1lh;
font-family: red hat mono, monospace;
text-align: right;
&::-webkit-textfield-decoration-container {
-webkt-user-modify: read-write !important;
//background: red;
}
&::-webkit-inner-spin-button {
-webkt-user-modify: read-write !important;
appearance: none;
}
&:invalid { background: crimson; }
}
[type='color'] {
flex: 0 0 1lh;
border: solid $line-w grey;
padding: $line-w;
height: 1lh;
border-radius: 50%;
&::-webkit-color-swatch {
border: none;
margin: -4px -2px;
border-radius: 50%
}
&::-moz-color-swatch {
border: none;
border-radius: 50%;
}
}
output {
&::after { content: var(--unit, ) }
}
/* ====== SPECIFIC COMPONENTS ====== */
.fxor, .grad {
isolation: isolate;
filter: url(#grad-xor);
&::before, &::after { mix-blend-mode: difference }
&::before { --dty: calc((1 - var(--hov))*var(--y)) }
&::after {
background: var(--func) fixed;
content: ''
}
}
.fxor { background: #f00 text }
.grad {
background: var(--grad)
var(--mode, #{unquote(' ')})
}
.wrap {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: $s;
&[class*='x'] {
display: grid;
grid-template-columns: max-content 1fr;
flex: 1 1 min(50%, 10em);
padding: $s 0;
}
}
.cont {
display: grid;
grid-template-rows: 100%;
align-items: center;
container-type: inline-size;
width: 100%;
height: 1lh;
}
.theme-switch {
grid-area: 1/ 1;
justify-items: end
}
[name='theme'] + [for] {
position: relative;
padding: 0 2*$s;
color: #0000;
background: var(--func) text fixed;
font:
Round(Max(.625rem, .75em), 1px)/ 2
orbitron, sans-serif;
cursor: pointer;
&::before {
--comp-0: var(--link-1);
--comp-1: var(--link-0);
position: absolute;
z-index: -1;
inset: 0;
border-radius: 1lh;
opacity: min(1, var(--hov) + var(--sel));
background: var(--func) fixed;
filter: Saturate(calc(var(--sel)*.5));
content: ''
}
&::after { content: attr(data-ico) }
}
.theme-controls {
top: 2.5lh;
flex: 1 2 14.5em;
border: solid $s var(--col);
border-radius: calc(#{$s} + 2*#{$line-w});
h2 { font-size: 1.25em }
&:has(#lin:checked) #pos,
&:has(#rad:checked) .wrap:has(#ang),
&:has(#rep:not(:checked)) .wrap:has(#num) { display: none }
}
View Compiled
addEventListener('input', e => {
let _t = e.target, v = _t.value, id = _t.id,
_o = _t.nextElementSibling, t = _t.type;
if(['range', 'color', 'number'].indexOf(t) > -1) {
switch(t) {
case 'range':
_o.style.setProperty('--val', v);
case 'color':
_o.textContent = v;
break;
case 'number':
if(!(v.length && v.match(/[0-9]{1,2}/) && +_t.min <= +v && +_t.max >= +v))
_t.value = v = _t.dataset.default
}
document.body.style.setProperty(
`--${id}`,
`${v}${getComputedStyle(_t).getPropertyValue('--unit') || ''}`)
}
})
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.