HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by Skypack, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ES6 import
usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
#app
*
*:after
*:before
box-sizing border-box
body
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
font-family -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif
min-height 100vh
display flex
align-items center
justify-content center
section
align-items center
height 100%
scroll-snap-align start
flex 1 0 100%
display flex
justify-content center
overflow auto
width 100%
position relative
#app
position relative
& > a
--neumorphic-reach 10
--neumorphic-blur 15
--neumorphic-intensity 0.75
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
--dark 'hsla(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity))
--light 'hsla(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
box-shadow '%s %s %s %s,
%s %s %s %s' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
position absolute
top 50%
height 44px
width 44px
background var(--default)
border-radius 50%
font-size 0
&:visited path
path
fill var(--dark)
&:hover path
&:focus path
fill var(--light)
&:active
border 4px solid white
path
fill white
&:not([href])
border 0
cursor not-allowed
path
fill var(--dark)
&:nth-of-type(1)
left 100%
transform translate(50%, -50%)
&:nth-of-type(2)
right 100%
transform translate(-50%, -50%)
svg
transform rotate(180deg)
main
--neumorphic-reach 30
--neumorphic-blur 60
--neumorphic-intensity 0.25
--border-width 0
--border-intensity 0.1
--border-radius 25
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
-webkit-overflow-scrolling touch
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
border '%s solid hsla(%s, %s, %s, %s)' % (calc(var(--border-width, 0) * 1px) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--border-intensity))
border-radius calc(var(--border-radius) * 1px)
box-shadow '%s %s %s hsla(%s, %s, %s, %s),
%s %s %s hsla(%s, %s, %s, %s)' % (var(--x) var(--y) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity) var(--x2) var(--y2) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
display flex
overflow auto
overflow-y hidden
position relative
scroll-behavior smooth
scroll-snap-type x mandatory
height 75vmin
width 75vmin
footer
position absolute
top calc(100% + 60px)
left 50%
transform translate(-50%)
display flex
a.active
background 'radial-gradient(circle at 50% 50%, hsl(%s, %s, %s) 20%, transparent 25%)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 30) * 1%))
a
height 44px
width 44px
border-radius 50%
font-size 0
display block
position relative
transition background .1s ease
&:hover:not(.active)
background 'radial-gradient(circle at 50% 50%, hsl(%s, %s, %s) 20%, transparent 25%)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 10) * 1%))
&:after
--neumorphic-reach 4
--neumorphic-blur 8
--neumorphic-intensity 0.25
--dark 'hsla(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity))
--light 'hsla(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
content ''
height 30px
width 30px
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
border-radius 50%
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
article
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
border '%s solid hsla(%s, %s, %s, %s)' % (calc(var(--border-width, 0) * 1px) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--border-intensity))
border-radius calc(var(--border-radius) * 1px)
box-shadow '%s %s %s hsla(%s, %s, %s, %s),
%s %s %s hsla(%s, %s, %s, %s)' % (var(--x) var(--y) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity) var(--x2) var(--y2) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
height calc(var(--height, 100) * 1px)
width calc(var(--width, 100) * 1px)
header
position fixed
height 75vmin
width 100vw
top 50%
left 50%
transform translate(-50%, -50%)
z-index -1
h1
color 'hsla(%s, %s, %s, 0.25)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 50) * 1%))
position absolute
z-index 2
font-weight bold
bottom 5%
right 5%
// transform translate(-50%, -100%)
label
color 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 50) * 1%))
@supports(-webkit-appearance: none)
input[type='checkbox']
input[type='radio']
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
--light 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%) var(--neumorphic-intensity))
--dark 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) var(--neumorphic-intensity))
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
--size 36
-webkit-appearance none
height calc(var(--size) * 1px)
outline none
margin 0
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
cursor pointer
border-style solid
border-color white
border-radius calc(var(--border-radius) * 1px)
border-width calc(var(--border-width) * 1px)
background var(--default)
transition box-shadow .1s
width calc(var(--size) * 1px)
&:checked
background 'radial-gradient(circle at center center, white 25%, transparent 25%), %s' % (var(--default))
&:checked + label
font-weight bold
input[type=radio]
box-shadow '%s %s %s %s,
%s %s %s %s' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
&:hover
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--blur calc(var(--neumorphic-blur) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
&:checked
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
// Range
input[type=range]
--thumb-size 36
--thumb-border 4
--thumb-angle 135
-webkit-appearance none
background transparent
width 100%
input[type=range]:focus
outline none
input[type=range]::-ms-track
background transparent
border-color transparent
color transparent
cursor pointer
width 100%
input[type=range]:focus::-webkit-slider-thumb
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 10) * 1%))
input[type=range]:focus::-moz-range-thumb
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 10) * 1%))
input[type=range]:focus::-ms-thumb
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 10) * 1%))
input[type=range]::-webkit-slider-thumb
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--dark 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
-webkit-appearance none
background 'linear-gradient(%s, %s, %s), %s' % (calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
background-size calc((var(--thumb-size) + var(--thumb-border)) * 1px) calc((var(--thumb-size) + var(--thumb-border)) * 1px)
background-position calc(var(--thumb-border) * -1px) calc(var(--thumb-border) * -1px)
border-style solid
border-width calc(var(--thumb-border) * 1px)
border-color transparent
border-radius calc(var(--border-radius) * 1px)
cursor pointer
height calc(var(--thumb-size) * 1px)
margin-top 0px
width calc(var(--thumb-size) * 1px)
&:hover
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
&:active
border-color white
input[type=range]::-moz-range-thumb
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--dark 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
background 'linear-gradient(%s, %s, %s), %s' % (calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
background-size calc((var(--thumb-size) + var(--thumb-border)) * 1px) calc((var(--thumb-size) + var(--thumb-border)) * 1px)
background-position calc(var(--thumb-border) * -1px) calc(var(--thumb-border) * -1px)
border-style solid
border-width calc(var(--thumb-border) * 1px)
border-color transparent
border-radius calc(var(--border-radius) * 1px)
cursor pointer
height calc(var(--thumb-size) * 1px)
width calc(var(--thumb-size) * 1px)
&:hover
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
&:active
border-color white
input[type=range]::-ms-thumb
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--dark 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
background 'linear-gradient(%s, %s, %s), %s' % (calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
background-size calc((var(--thumb-size) + var(--thumb-border)) * 1px) calc((var(--thumb-size) + var(--thumb-border)) * 1px)
background-position calc(var(--thumb-border) * -1px) calc(var(--thumb-border) * -1px)
border-style solid
border-width calc(var(--thumb-border) * 1px)
border-color transparent
border-radius calc(var(--border-radius) * 1px)
cursor pointer
height calc(var(--thumb-size) * 1px)
width calc(var(--thumb-size) * 1px)
&:hover
border-color 'hsla(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
&:active
border-color white
input[type=range]::-webkit-slider-runnable-track
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--neumorphic-light 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%) var(--neumorphic-intensity))
--neumorphic-dark 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) var(--neumorphic-intensity))
background var(--default)
border-radius calc(var(--border-radius) * 1px)
border-color var(--light)
border-style solid
border-width 0
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--neumorphic-dark) var(--x2) var(--y2) var(--blur) var(--neumorphic-light))
cursor pointer
height calc(var(--thumb-size) * 1px)
width 100%
input[type=range]:focus::-webkit-slider-runnable-track
--track 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) var(--track-intensity))
background var(--track)
// input[type=range]:active::-webkit-slider-runnable-track
// --track 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) calc(var(--track-intensity) * 2))
// background var(--track)
input[type=range]::-moz-range-track
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--neumorphic-light 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%) var(--neumorphic-intensity))
--neumorphic-dark 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) var(--neumorphic-intensity))
background var(--default)
border-radius calc(var(--border-radius) * 1px)
border-color var(--light)
border-style solid
border-width 0
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--neumorphic-dark) var(--x2) var(--y2) var(--blur) var(--neumorphic-light))
cursor pointer
height calc(var(--thumb-size) * 1px)
width 100%
input[type=range]::-ms-track
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--blur calc(var(--neumorphic-blur) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
--default 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
--light 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
--neumorphic-light 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%) var(--neumorphic-intensity))
--neumorphic-dark 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%) var(--neumorphic-intensity))
background var(--default)
border-radius calc(var(--border-radius) * 1px)
border-color var(--light)
border-style solid
border-width 0
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--neumorphic-dark) var(--x2) var(--y2) var(--blur) var(--neumorphic-light))
cursor pointer
height calc(var(--thumb-size) * 1px)
width 100%
// Buttons
button
--blur calc(var(--neumorphic-blur) * 1px)
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
-webkit-appearance none
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
color 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 40) * 1%))
border '%s solid hsla(%s, %s, %s, %s)' % (calc(var(--border-width, 0) * 1px) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--border-intensity))
border-radius calc(var(--border-radius) * 1px)
box-shadow '%s %s %s hsla(%s, %s, %s, %s),
%s %s %s hsla(%s, %s, %s, %s)' % (var(--x) var(--y) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity) var(--x2) var(--y2) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
font-size 1rem
font-weight 500
overflow hidden
outline transparent
padding 1rem 2rem
position relative
transition all .1s ease
&:after
bottom 0
content ''
height 15%
left 0
position absolute
width 100%
&:active
box-shadow '%s %s %s hsla(%s, %s, %s, %s) inset,
%s %s %s hsla(%s, %s, %s, %s) inset' % (var(--x) var(--y) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity) var(--x2) var(--y2) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
&:hover:after
&:focus:after
background 'hsla(%s, %s, %s, 0.35)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 40) * 1%))
&:active:after
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 40) * 1%))
&:nth-of-type(2)
&:active
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 40) * 1%))
box-shadow none
color 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 40) * 1%))
&:nth-of-type(3)
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
color 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
&:after
display none
&:hover
&:focus
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 30) * 1%))
&:active
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 40) * 1%))
box-shadow none
color 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 40) * 1%))
// Text
[type='text']
--blur calc(var(--neumorphic-blur) * 1px)
--x calc(var(--neumorphic-reach) * 1px)
--y calc(var(--neumorphic-reach) * 1px)
--x2 calc(var(--neumorphic-reach) * -1px)
--y2 calc(var(--neumorphic-reach) * -1px)
background 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc(var(--lightness) * 1%))
border-color transparent
border-radius calc(var(--border-radius) * 1px)
border-style solid
border-width calc(var(--border-width) * 1px)
font-size 1rem
outline transparent
overflow hidden
padding 1rem 2rem
box-shadow '%s %s %s hsla(%s, %s, %s, %s) inset,
%s %s %s hsla(%s, %s, %s, %s) inset' % (var(--x) var(--y) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 15) * 1%) var(--neumorphic-intensity) var(--x2) var(--y2) var(--blur) var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 15) * 1%) var(--neumorphic-intensity))
&:focus
border-color var(--highlight)
// Layout related fun
.buttons
.texts
.ranges
.checkboxes
.radios
display grid
grid-gap calc(var(--margin) * 4px)
width 30vmin
.radios
.checkboxes
width auto
.input
align-items center
display grid
grid-template-columns auto 1fr
grid-gap 1rem
// Label highlights for accentuating focus
.texts
.ranges
.input
&:focus-within label
font-weight bold
&:nth-of-type(1)
--highlight 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 20) * 1%))
&:nth-of-type(2)
--highlight 'hsl(%s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
&:nth-of-type(3)
&:focus-within label
color white
--highlight transparent
.ranges .input
&:nth-of-type(1)
--track-intensity 0
&:nth-of-type(2)
input[type=range]::-webkit-slider-thumb:active
--dark 'hsl(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
background var(--dark)
input[type=range]::-moz-range-thumb:active
--dark 'hsl(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
background var(--dark)
input[type=range]::-ms-thumb:active
--dark 'hsl(%s, %s, %s, 1)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) - 20) * 1%))
background var(--dark)
&:nth-of-type(3)
&:focus-within input[type=range]::-webkit-slider-thumb
--dot-alpha 0.25
input[type=range]::-webkit-slider-thumb
--thumb-border 0
--dot-alpha 0
--dot-color 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 40) * 1%) var(--dot-alpha))
background 'radial-gradient(circle at 50% 50%, %s 25%, transparent 25%), linear-gradient(%s, %s, %s), %s' % (var(--dot-color) calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
&:focus
--dot-alpha 0.25
&:hover
--dot-alpha 0.5
&:active
--dot-alpha 1
--thumb-angle -45
input[type=range]::-moz-range-thumb
--thumb-border 0
--dot-alpha 0
--dot-color 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 40) * 1%) var(--dot-alpha))
background 'radial-gradient(circle at 50% 50%, %s 25%, transparent 25%), linear-gradient(%s, %s, %s), %s' % (var(--dot-color) calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
&:focus
--dot-alpha 0.25
&:hover
--dot-alpha 0.5
&:active
--dot-alpha 1
--thumb-angle -45
input[type=range]::-ms-thumb
--thumb-border 0
--dot-alpha 0
--dot-color 'hsl(%s, %s, %s, %s)' % (var(--hue) calc(var(--saturation) * 1%) calc((var(--lightness) + 40) * 1%) var(--dot-alpha))
background 'radial-gradient(circle at 50% 50%, %s 25%, transparent 25%), linear-gradient(%s, %s, %s), %s' % (var(--dot-color) calc(var(--thumb-angle) * 1deg) var(--light) var(--dark) var(--default))
&:focus
--dot-alpha 0.25
&:hover
--dot-alpha 0.5
&:active
--dot-alpha 1
--thumb-angle -45
.checkboxes .input
input
&:focus + label
font-weight bold
transition all .1s ease
&:nth-of-type(1)
input
box-shadow '%s %s %s %s,
%s %s %s %s' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
&:hover
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
&:focus + label
font-weight bold
&:hover
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 0.5) 25%, transparent 25%), %s' % (var(--default))
&:checked
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 1) 25%, transparent 25%), %s' % (var(--default))
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
&:nth-of-type(2)
input
&:hover
&:focus
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
&:hover
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 0.5) 25%, transparent 25%), %s' % (var(--default))
&:checked
--neumorphic-intensity 1
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 1) 25%, %s 25%), %s' % (var(--dark) var(--default))
box-shadow none
.radios .input
input
&:focus + label
font-weight bold
transition all .1s ease
&:nth-of-type(1)
input
box-shadow '%s %s %s %s,
%s %s %s %s' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
&:hover
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
&:focus + label
font-weight bold
&:hover
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 0.5) 25%, transparent 25%), %s' % (var(--default))
&:checked
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 1) 25%, transparent 25%), %s' % (var(--default))
box-shadow '%s %s %s %s inset,
%s %s %s %s inset' % (var(--x) var(--y) var(--blur) var(--dark) var(--x2) var(--y2) var(--blur) var(--light))
&:nth-of-type(2)
input
&:hover
&:focus
--x calc(var(--neumorphic-reach) * 2px)
--y calc(var(--neumorphic-reach) * 2px)
--x2 calc(var(--neumorphic-reach) * -2px)
--y2 calc(var(--neumorphic-reach) * -2px)
&:hover
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 0.5) 25%, transparent 25%), %s' % (var(--default))
&:checked
--neumorphic-intensity 1
background 'radial-gradient(circle at center center, hsla(0, 0%, 100%, 1) 25%, %s 25%), %s' % (var(--dark) var(--default))
box-shadow none
const {
dat: { GUI },
React,
React: { useEffect, useRef, useState, Fragment },
ReactDOM: { render },
// ScrollOut,
} = window
const CONFIG = {
COLOR: {
HUE: 225,
SATURATION: 40,
LIGHTNESS: 65,
},
CARD: {
BORDER: {
WIDTH: 0,
RADIUS: 10,
ALPHA: 0.1,
},
SHADOW: {
REACH: 30,
BLUR: 60,
ALPHA: 0.65,
},
SIZE: {
HEIGHT: 200,
WIDTH: 200,
},
},
BUTTON: {
BORDER: {
WIDTH: 0,
RADIUS: 10,
ALPHA: 0.1,
},
SHADOW: {
REACH: 5,
BLUR: 10,
ALPHA: 0.5,
},
},
TEXT: {
BORDER: {
WIDTH: 2,
RADIUS: 10,
ALPHA: 0.1,
},
SHADOW: {
REACH: 4,
BLUR: 8,
ALPHA: 0.5,
},
},
RANGE: {
BORDER: {
RADIUS: 36,
},
SHADOW: {
REACH: 4,
BLUR: 8,
ALPHA: 0.5,
},
TRACK: {
ALPHA: 0.2,
},
},
CHECKBOX: {
BORDER: {
RADIUS: 36,
},
SHADOW: {
REACH: 4,
BLUR: 8,
ALPHA: 0.5,
},
},
RADIO: {
BORDER: {
WIDTH: 0,
RADIUS: 36,
},
SHADOW: {
REACH: 4,
BLUR: 8,
ALPHA: 0.5,
},
},
}
const BOUNDS = {
COLOR: {
HUE: [0, 360, 1],
SATURATION: [0, 100, 1],
LIGHTNESS: [0, 100, 1],
},
CARD: {
BORDER: {
WIDTH: [0, 10, 1],
ALPHA: [0, 1, 0.01],
RADIUS: [0, 50, 1],
},
SHADOW: {
BLUR: [0, 100, 1],
REACH: [0, 50, 1],
ALPHA: [0.2, 1, 0.01],
},
SIZE: {
HEIGHT: [50, 300, 1],
WIDTH: [50, 300, 1],
},
},
BUTTON: {
BORDER: {
WIDTH: [0, 10, 1],
ALPHA: [0, 1, 0.01],
RADIUS: [0, 50, 1],
},
SHADOW: {
BLUR: [0, 100, 1],
REACH: [0, 50, 1],
ALPHA: [0.2, 1, 0.01],
},
},
TEXT: {
BORDER: {
WIDTH: [0, 10, 1],
RADIUS: [0, 40, 1],
ALPHA: [0, 1, 0.01],
},
SHADOW: {
REACH: [0, 20, 1],
BLUR: [0, 40, 1],
ALPHA: [0, 1, 0.1],
},
},
RANGE: {
BORDER: {
RADIUS: [0, 36, 1],
},
SHADOW: {
REACH: [0, 20, 1],
BLUR: [0, 40, 1],
ALPHA: [0, 1, 0.1],
},
TRACK: {
ALPHA: [0, 1, 0.01],
},
},
CHECKBOX: {
BORDER: {
RADIUS: [0, 36, 1],
},
SHADOW: {
REACH: [0, 20, 1],
BLUR: [0, 40, 1],
ALPHA: [0, 1, 0.1],
},
},
RADIO: {
BORDER: {
WIDTH: [0, 10, 1],
RADIUS: [0, 36, 1],
},
SHADOW: {
REACH: [0, 20, 1],
BLUR: [0, 40, 1],
ALPHA: [0, 1, 0.1],
},
},
}
const CARD_ID = '#cards'
const BUTTON_ID = '#buttons'
const TEXT_ID = '#texts'
const RANGE_ID = '#ranges'
const CHECKBOX_ID = '#checkboxes'
const RADIO_ID = '#radios'
const IDS = [CARD_ID, BUTTON_ID, TEXT_ID, RANGE_ID, CHECKBOX_ID, RADIO_ID]
const App = () => {
const [model, setModel] = useState(0)
const [active, setActive] = useState(window.location.hash || IDS[0])
const [next, setNext] = useState(IDS[IDS.indexOf(active) + 1])
const [prev, setPrev] = useState(IDS[IDS.indexOf(active) - 1])
const datRef = useRef(null)
useEffect(() => {
if (!datRef.current) {
datRef.current = new GUI({ name: 'Neumorphic Playground' })
const digest = (CONFIG_OBJECT, BOUNDS_OBJECT, FOLDER) => {
for (const category in BOUNDS_OBJECT) {
if (Array.isArray(BOUNDS_OBJECT[category])) {
FOLDER.add(
CONFIG_OBJECT,
category,
BOUNDS_OBJECT[category][0],
BOUNDS_OBJECT[category][1],
BOUNDS_OBJECT[category][2] ? BOUNDS_OBJECT[category][2] : 1
).onChange(() => setModel(new Date().getTime()))
} else {
const NEW_FOLDER = FOLDER
? FOLDER.addFolder(category)
: datRef.current.addFolder(category)
digest(CONFIG_OBJECT[category], BOUNDS_OBJECT[category], NEW_FOLDER)
}
}
}
digest(CONFIG, BOUNDS)
}
// Set HSL on document
document.documentElement.style.setProperty('--hue', CONFIG.COLOR.HUE)
document.documentElement.style.setProperty(
'--saturation',
CONFIG.COLOR.SATURATION
)
document.documentElement.style.setProperty(
'--lightness',
CONFIG.COLOR.LIGHTNESS
)
}, [model])
// Set up scroll out
useEffect(() => {
ScrollOut({
scrollingElement: document.querySelector('main'),
targets: 'section',
threshold: 0.9,
onShown: element => {
setActive(`#${element.getAttribute('id')}`)
},
})
}, [])
useEffect(() => {
setNext(IDS[IDS.indexOf(active) + 1])
setPrev(IDS[IDS.indexOf(active) - 1])
}, [active])
return (
<Fragment>
<main>
<section
id="cards"
style={{
'--neumorphic-reach': CONFIG.CARD.SHADOW.REACH,
'--neumorphic-blur': CONFIG.CARD.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.CARD.SHADOW.ALPHA,
'--border-width': CONFIG.CARD.BORDER.WIDTH,
'--border-intensity': CONFIG.CARD.BORDER.ALPHA,
'--border-radius': CONFIG.CARD.BORDER.RADIUS,
'--height': CONFIG.CARD.SIZE.HEIGHT,
'--width': CONFIG.CARD.SIZE.WIDTH,
}}>
<article />
<h1>Card</h1>
</section>
<section
id="buttons"
style={{
'--neumorphic-reach': CONFIG.BUTTON.SHADOW.REACH,
'--neumorphic-blur': CONFIG.BUTTON.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.BUTTON.SHADOW.ALPHA,
'--border-width': CONFIG.BUTTON.BORDER.WIDTH,
'--border-intensity': CONFIG.BUTTON.BORDER.ALPHA,
'--border-radius': CONFIG.BUTTON.BORDER.RADIUS,
'--margin': Math.max(
CONFIG.BUTTON.SHADOW.REACH,
CONFIG.BUTTON.SHADOW.BLUR
),
}}>
<div className="buttons">
<button>Click</button>
<button>Click</button>
<button>Click</button>
</div>
<h1>Button</h1>
</section>
<section
id="texts"
style={{
'--neumorphic-reach': CONFIG.TEXT.SHADOW.REACH,
'--neumorphic-blur': CONFIG.TEXT.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.TEXT.SHADOW.ALPHA,
'--border-width': CONFIG.TEXT.BORDER.WIDTH,
'--border-intensity': CONFIG.TEXT.BORDER.ALPHA,
'--border-radius': CONFIG.TEXT.BORDER.RADIUS,
'--margin': 6,
}}>
<div className="texts">
<div className="input">
<label htmlFor="text-1">Label</label>
<input id="text-1" type="text" />
</div>
<div className="input">
<label htmlFor="text-2">Label</label>
<input id="text-2" type="text" />
</div>
<div className="input">
<label htmlFor="text-3">Label</label>
<input id="text-3" type="text" />
</div>
</div>
<h1>Text</h1>
</section>
<section
id="ranges"
style={{
'--neumorphic-reach': CONFIG.RANGE.SHADOW.REACH,
'--neumorphic-blur': CONFIG.RANGE.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.RANGE.SHADOW.ALPHA,
'--track-intensity': CONFIG.RANGE.TRACK.ALPHA,
'--border-width': CONFIG.RANGE.BORDER.WIDTH,
'--border-intensity': CONFIG.RANGE.BORDER.ALPHA,
'--border-radius': CONFIG.RANGE.BORDER.RADIUS,
'--margin': 15,
}}>
<div className="ranges">
<div className="input">
<label htmlFor="range-1">Label</label>
<input
id="range-1"
type="range"
min="0"
max="10"
step="1"
defaultValue="2"
/>
</div>
<div className="input">
<label htmlFor="range-2">Label</label>
<input
id="range-2"
type="range"
min="0"
max="10"
step="1"
defaultValue="4"
/>
</div>
<div className="input">
<label htmlFor="range-3">Label</label>
<input
id="range-3"
type="range"
min="0"
max="10"
step="1"
defaultValue="6"
/>
</div>
</div>
<h1>Range</h1>
</section>
<section
id="checkboxes"
style={{
'--neumorphic-reach': CONFIG.CHECKBOX.SHADOW.REACH,
'--neumorphic-blur': CONFIG.CHECKBOX.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.CHECKBOX.SHADOW.ALPHA,
'--border-width': CONFIG.CHECKBOX.BORDER.WIDTH,
'--border-intensity': CONFIG.CHECKBOX.BORDER.ALPHA,
'--border-radius': CONFIG.CHECKBOX.BORDER.RADIUS,
'--margin': 15,
}}>
<div className="checkboxes">
<div className="input">
<input id="check-1" type="checkbox" />
<label htmlFor="check-1">Check</label>
</div>
<div className="input">
<input id="check-2" type="checkbox" />
<label htmlFor="check-2">Check</label>
</div>
<div className="input">
<input id="check-3" type="checkbox" />
<label htmlFor="check-3">Check</label>
</div>
</div>
<h1>Checkbox</h1>
</section>
<section
id="radios"
style={{
'--neumorphic-reach': CONFIG.RADIO.SHADOW.REACH,
'--neumorphic-blur': CONFIG.RADIO.SHADOW.BLUR,
'--neumorphic-intensity': CONFIG.RADIO.SHADOW.ALPHA,
'--border-width': CONFIG.RADIO.BORDER.WIDTH,
'--border-intensity': CONFIG.RADIO.BORDER.ALPHA,
'--border-radius': CONFIG.RADIO.BORDER.RADIUS,
'--margin': 15,
}}>
<div className="radios">
<div className="input radio">
<input id="radio-1-1" type="radio" name="radio-one" checked />
<label htmlFor="radio-1-1">Radio</label>
<input id="radio-1-2" type="radio" name="radio-one" />
<label htmlFor="radio-1-2">Radio</label>
</div>
<div className="input radio">
<input id="radio-2-1" type="radio" name="radio-two" checked />
<label htmlFor="radio-2-1">Radio</label>
<input id="radio-2-2" type="radio" name="radio-two" />
<label htmlFor="radio-2-2">Radio</label>
</div>
<div className="input radio">
<input id="radio-3-1" type="radio" name="radio-three" checked />
<label htmlFor="radio-3-1">Radio</label>
<input id="radio-3-2" type="radio" name="radio-three" />
<label htmlFor="radio-3-2">Radio</label>
</div>
</div>
<h1>Radio</h1>
</section>
</main>
<footer>
{IDS.map(ID => {
return (
<a href={ID} key={ID} className={`${active === ID && 'active'}`}>
{`${ID.charAt(1).toUpperCase()}${ID.substr(2)}`}
</a>
)
})}
</footer>
<a href={next}>
Next
<svg viewBox="0 0 24 24">
<path
fill="currentColor"
d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z"
/>
</svg>
</a>
<a href={prev}>
Prev
<svg viewBox="0 0 24 24">
<path
fill="currentColor"
d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z"
/>
</svg>
</a>
</Fragment>
)
}
render(<App />, document.getElementById('app'))
Also see: Tab Triggers