<button class="theme-toggle" id="theme-toggle" title="Toggles light & dark" aria-label="auto" aria-live="polite">
<svg class="sun-and-moon" aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">
<mask class="moon" id="moon-mask">
<rect x="0" y="0" width="100%" height="100%" fill="white" />
<circle cx="24" cy="10" r="6" fill="black" />
</mask>
<circle class="sun" cx="12" cy="12" r="6" mask="url(#moon-mask)" fill="currentColor" />
<g class="sun-beams" stroke="currentColor">
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
<line x1="1" y1="12" x2="3" y2="12" />
<line x1="21" y1="12" x2="23" y2="12" />
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</g>
</svg>
</button>
@ import "https://unpkg.com/open-props/easings.min.css" ;
. sun-and-moon > : is ( . moon , . sun , . sun-beams ) {
transform-origin : center ;
}
. sun-and-moon > : is ( . moon , . sun ) {
fill : var ( --icon-fill );
}
. theme-toggle : is ( : hover , : focus-visible ) > . sun-and-moon > : is ( . moon , . sun ) {
fill : var ( --icon-fill-hover );
}
. sun-and-moon > . sun-beams {
stroke : var ( --icon-fill );
stroke-width : 2 px ;
}
. theme-toggle : is ( : hover , : focus-visible ) . sun-and-moon > . sun-beams {
stroke : var ( --icon-fill-hover );
}
[ data-theme = "dark" ] . sun-and-moon > . sun {
transform : scale ( 1.75 );
}
[ data-theme = "dark" ] . sun-and-moon > . sun-beams {
opacity : 0 ;
}
[ data-theme = "dark" ] . sun-and-moon > . moon > circle {
transform : translateX ( -7 px );
}
@ supports ( cx : 1 ) {
[ data-theme = "dark" ] . sun-and-moon > . moon > circle {
cx : 17 ;
transform : translateX ( 0 );
}
}
@ media ( prefers-reduced-motion : no-preference ) {
. sun-and-moon > . sun {
transition : transform .5 s var ( --ease-elastic- 3 );
}
. sun-and-moon > . sun-beams {
transition : transform .5 s var ( --ease-elastic- 4 ), opacity .5 s var ( --ease- 3 );
}
. sun-and-moon . moon > circle {
transition : transform .25 s var ( --ease-out- 5 );
}
@ supports ( cx : 1 ) {
. sun-and-moon . moon > circle {
transition : cx .25 s var ( --ease-out- 5 );
}
}
[ data-theme = "dark" ] . sun-and-moon > . sun {
transition-timing-function : var ( --ease- 3 );
transition-duration : .25 s ;
transform : scale ( 1.75 );
}
[ data-theme = "dark" ] . sun-and-moon > . sun-beams {
transition-duration : .15 s ;
transform : rotateZ ( -25 deg );
}
[ data-theme = "dark" ] . sun-and-moon > . moon > circle {
transition-duration : .5 s ;
transition-delay : .25 s ;
}
}
const storageKey = 'theme-preference'
const onClick = () => {
// flip current value
theme . value = theme . value === 'light'
? 'dark'
: 'light'
setPreference ()
}
const getColorPreference = () => {
if ( localStorage . getItem ( storageKey ))
return localStorage . getItem ( storageKey )
else
return window . matchMedia ( '(prefers-color-scheme: dark)' ). matches
? 'dark'
: 'light'
}
const setPreference = () => {
localStorage . setItem ( storageKey , theme . value )
reflectPreference ()
}
const reflectPreference = () => {
document . firstElementChild
. setAttribute ( 'data-theme' , theme . value )
document
. querySelector ( '#theme-toggle' )
? . setAttribute ( 'aria-label' , theme . value )
}
const theme = {
value : getColorPreference (),
}
// set early so no page flashes / CSS is made aware
reflectPreference ()
window . onload = () => {
// set on load so screen readers can see latest value on the button
reflectPreference ()
// now this script can find and listen for clicks on the control
document
. querySelector ( '#theme-toggle' )
. addEventListener ( 'click' , onClick )
}
// sync with system changes
window
. matchMedia ( '(prefers-color-scheme: dark)' )
. addEventListener ( 'change' , ({ matches : isDark }) => {
theme . value = isDark ? 'dark' : 'light'
setPreference ()
})
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License , and code samples are licensed under the Apache 2.0 License . For details, see the Google Developers Site Policies . Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2023-07-05 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2023-07-05 UTC."],[],[]]