Mantieni tutto organizzato con le raccolte
Salva e classifica i contenuti in base alle tue preferenze.
HTML
<main>
<h1>Settings</h1>
<form>
<section>
<header>
<h2>Sound & vibration</h2>
<small>Adjust system volume channels</small>
</header>
<fieldset>
<div class="fieldset-item">
<picture aria-hidden="true">
<svg viewBox="0 0 24 24">
<title>A note icon</title>
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
</picture>
<div class="input-stack">
<label
for="media-volume"
id="media-volume"
aria-hidden="true">
Media volume
</label>
<input
name="media-volume"
aria-labelledby="media-volume"
type="range"
value="3"
max="10"
style="--track-fill: 30%"
>
</div>
</div>
<div class="fieldset-item">
<picture aria-hidden="true">
<title>A phone icon</title>
<svg viewBox="0 0 24 24">
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/>
</svg>
</picture>
<div class="input-stack">
<label for="call-volume" id="call-volume" aria-hidden="true">Call volume</label>
<input
name="call-volume"
aria-labelledby="call-volume"
type="range"
value="7"
max="10"
style="--track-fill: 70%"
>
</div>
</div>
<div class="fieldset-item">
<picture aria-hidden="true">
<svg viewBox="0 0 24 24">
<title>A bell icon</title>
<path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"/>
</svg>
</picture>
<div class="input-stack">
<label for="ring-volume" id="ring-volume" aria-hidden="true">Ring volume</label>
<input
name="ring-volume"
aria-labelledby="ring-volume"
type="range"
value="5"
max="10"
style="--track-fill: 50%"
>
</div>
</div>
<div class="fieldset-item">
<picture aria-hidden="true">
<svg viewBox="0 0 24 24">
<title>An alarm clock icon</title>
<path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/>
</svg>
</picture>
<div class="input-stack">
<label for="alarm-volume" id="alarm-volume" aria-hidden="true">Alarm volume</label>
<input
name="alarm-volume"
aria-labelledby="alarm-volume"
type="range"
value="8"
max="10"
style="--track-fill: 80%"
>
</div>
</div>
</fieldset>
</section>
<section>
<header>
<h2>Notifications</h2>
<small>Turn specific channels on/off</small>
</header>
<fieldset>
<div class="fieldset-item">
<input
type="checkbox"
checked
id="text-notifications"
name="text-notifications"
>
<div class="input-stack">
<label for="text-notifications">
<h3>Text Messages</h3>
<small>Get notified about all text messages sent to your device</small>
</label>
</div>
</div>
<div class="fieldset-item">
<input
type="checkbox"
id="voice-notifications"
name="voice-notifications"
>
<div class="input-stack">
<label for="voice-notifications">
<h3>Voice Mail</h3>
<small>Get notified about all voice messages sent to your device</small>
</label>
</div>
</div>
<div class="fieldset-item">
<input
type="checkbox"
id="email-notifications"
name="email-notifications"
>
<div class="input-stack">
<label for="email-notifications">
<h3>Emails</h3>
<small>Get notified about all text messages to your device</small>
</label>
</div>
</div>
</fieldset>
</section>
</form>
</main>
CSS
@custom-media --motionOK (prefers-reduced-motion: no-preference);
:root {
--surface1: lch(10 0 0);
--surface2: lch(15 0 0);
--surface3: lch(20 0 0);
--surface4: lch(25 0 0);
--text1: lch(95 0 0);
--text2: lch(75 0 0);
--brand: lch(64 20 237);
--brand-bg1: lch(70 64 349);
--brand-bg2: lch(60 84 300);
--brand-bg-gradient: linear-gradient(
to bottom,
var(--brand-bg1),
var(--brand-bg2)
);
--thumb-highlight-color: lch(100 0 0 / 20%);
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
--isLTR: 1;
--isRTL: -1;
&:dir(rtl) {
--isLTR: -1;
--isRTL: 1;
}
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--surface2: lch(100 0 0);
--surface3: lch(98 0 0);
--surface4: lch(85 0 0);
--text1: lch(20 0 0);
--text2: lch(40 0 0);
--brand: lch(64 40 237);
--brand-bg1: lch(50 64 349);
--brand-bg2: lch(40 84 300);
--thumb-highlight-color: lch(0 0 0 / 20%);
}
}
}
html {
block-size: 100%;
inline-size: 100%;
}
body {
min-block-size: 100%;
min-inline-size: 100%;
box-sizing: border-box;
margin: 0;
padding-block: var(--space-xs);
background: var(--surface1);
color: var(--text1);
font-family: system-ui, sans-serif;
}
h1,h2,h3 {
margin: 0;
font-weight: 500;
}
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
@media (width >= 540px) {
padding: var(--space-lg);
}
@media (width >= 800px) {
padding: var(--space-xl);
}
}
form {
max-width: 89vw;
display: grid;
gap: var(--space-xl) var(--space-xxl);
--repeat: auto-fit;
grid-template-columns:
repeat(var(--repeat), minmax(min(10ch, 100%), 35ch));
align-items: flex-start;
@media (orientation: landscape) and (width >= 640px) {
--repeat: 2;
}
}
section {
display: grid;
gap: var(--space-md);
}
header {
display: grid;
gap: var(--space-xxs);
}
fieldset {
border: 1px solid var(--surface4);
background: var(--surface4);
padding: 0;
margin: 0;
display: grid;
gap: 1px;
border-radius: var(--space-sm);
overflow: hidden;
transition: box-shadow .3s ease;
&:focus-within {
box-shadow: 0 5px 20px -10px hsl(0 0% 0% / 50%);
}
}
input[type="range"] {
--track-height: .5ex;
--track-fill: 0%;
--thumb-size: 3ex;
--thumb-offset: -1.25ex;
--thumb-highlight-size: 0px;
display: block;
inline-size: 100%;
margin: 1ex 0;
appearance: none;
background: transparent;
outline-offset: 5px;
@media (hover: none) {
--thumb-size: 30px;
--thumb-offset: -14px;
}
&::-webkit-slider-runnable-track {
appearance: none;
block-size: var(--track-height);
border-radius: 5ex;
background:
linear-gradient(
to right,
transparent var(--track-fill),
var(--surface1) 0%
),
var(--brand-bg-gradient) fixed;
}
&::-moz-range-track {
appearance: none;
block-size: var(--track-height);
border-radius: 5ex;
background:
linear-gradient(
to right,
transparent var(--track-fill),
var(--surface1) 0%
),
var(--brand-bg-gradient) fixed;
}
&::-webkit-slider-thumb {
appearance: none;
cursor: ew-resize;
border: 3px solid var(--surface3);
block-size: var(--thumb-size);
inline-size: var(--thumb-size);
margin-block-start: var(--thumb-offset);
border-radius: 50%;
background: var(--brand-bg-gradient) fixed;
box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
@media (--motionOK) {
transition: box-shadow .1s ease;
}
@nest .fieldset-item:focus-within & {
border-color: var(--surface2);
}
}
&::-moz-range-thumb {
appearance: none;
cursor: ew-resize;
border: 3px solid var(--surface3);
block-size: var(--thumb-size);
inline-size: var(--thumb-size);
margin-block-start: var(--thumb-offset);
border-radius: 50%;
background: var(--brand-bg-gradient) fixed;
box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
@media (--motionOK) {
transition: box-shadow .1s ease;
}
@nest .fieldset-item:focus-within & {
border-color: var(--surface2);
}
}
&:is(:hover,:active) {
--thumb-highlight-size: 10px;
}
}
input[type="checkbox"] {
inline-size: var(--space-sm);
block-size: var(--space-sm);
margin: 0;
outline-offset: 5px;
accent-color: var(--brand);
position: relative;
transform-style: preserve-3d;
cursor: pointer;
&:hover::before {
--thumb-scale: 1;
}
@media (hover: none) {
inline-size: var(--space-md);
block-size: var(--space-md);
}
&::before {
--thumb-scale: .01;
--thumb-highlight-size: var(--space-xl);
content: "";
inline-size: var(--thumb-highlight-size);
block-size: var(--thumb-highlight-size);
clip-path: circle(50%);
position: absolute;
inset-block-start: 50%;
inset-inline-start: 50%;
background: var(--thumb-highlight-color);
transform-origin: center center;
transform:
translateX(calc(var(--isRTL) * 50%))
translateY(-50%)
translateZ(-1px)
scale(var(--thumb-scale))
;
will-change: transform;
@media (--motionOK) {
transition: transform .2s ease;
}
}
}
.fieldset-item {
background: var(--surface3);
transition: background .2s ease;
display: grid;
grid-template-columns: var(--space-lg) 1fr;
gap: var(--space-md);
padding-block: var(--space-sm);
padding-inline: var(--space-md);
@media (width >= 540px) {
grid-template-columns: var(--space-xxl) 1fr;
gap: var(--space-xs);
padding-block: var(--space-md);
padding-inline: 0 var(--space-xl);
}
&:focus-within {
background: var(--surface2);
& svg {
fill: white;
}
& picture {
clip-path: circle(50%);
background: var(--brand-bg-gradient) fixed;
}
}
& > :is(.input-stack, label) {
display: grid;
gap: var(--space-xs);
}
& > .input-stack > label {
display: contents;
}
& > picture {
block-size: var(--space-xl);
inline-size: var(--space-xl);
clip-path: circle(40%);
display: inline-grid;
place-content: center;
background: var(--surface3) fixed;
@media (--motionOK) {
transition: clip-path .3s ease;
}
}
& svg {
fill: var(--text2);
block-size: var(--space-md);
}
& > :is(picture, input[type="checkbox"]) {
place-self: center;
}
}
small {
color: var(--text2);
line-height: 1.5;
}
JS
const form = document.querySelector('form')
const sliders = document.querySelectorAll('input[type="range"]')
const rangeToPercent = slider => {
const max = slider.getAttribute('max') || 10
const percent = slider.value / max * 100
return `${parseInt(percent)}%`
}
sliders.forEach(slider => {
slider.style.setProperty('--track-fill', rangeToPercent(slider))
slider.addEventListener('input', e => {
e.target.style.setProperty('--track-fill', rangeToPercent(e.target))
})
})
form.addEventListener('input', e => {
const formData = Object.fromEntries(new FormData(form))
console.table(formData)
})
Salvo quando diversamente specificato, i contenuti di questa pagina sono concessi in base alla licenza Creative Commons Attribution 4.0, mentre gli esempi di codice sono concessi in base alla licenza Apache 2.0. Per ulteriori dettagli, consulta le norme del sito di Google Developers. Java è un marchio registrato di Oracle e/o delle sue consociate.
Ultimo aggiornamento 2023-10-25 UTC.
[{
"type": "thumb-down",
"id": "missingTheInformationINeed",
"label":"Mancano le informazioni di cui ho bisogno"
},{
"type": "thumb-down",
"id": "tooComplicatedTooManySteps",
"label":"Troppo complicato/troppi passaggi"
},{
"type": "thumb-down",
"id": "outOfDate",
"label":"Obsoleti"
},{
"type": "thumb-down",
"id": "translationIssue",
"label":"Problema di traduzione"
},{
"type": "thumb-down",
"id": "samplesCodeIssue",
"label":"Problema relativo a esempi/codice"
},{
"type": "thumb-down",
"id": "otherDown",
"label":"Altra"
}]
[{
"type": "thumb-up",
"id": "easyToUnderstand",
"label":"Facile da capire"
},{
"type": "thumb-up",
"id": "solvedMyProblem",
"label":"Il problema è stato risolto"
},{
"type": "thumb-up",
"id": "otherUp",
"label":"Altra"
}]