Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

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.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                .app
    .left
    .right
        button.getGradient Get CSS

h1.leftHeading Base
h1.rightHeading Css

.overlay
    h1 Add 2+ colors to create a gradient
              
            
!

CSS

              
                @import url('https://fonts.googleapis.com/css?family=Prompt:700')

.app
    width: 100%
    height: 100vh
    box-sizing: border-box
    display: flex
    overflow: hidden
.left, .right
    width: 50%
    min-height: inherit
    
.left
    display: flex
    flex-direction: column
    height: 101vh
    > div
        width: 100%
        display: flex
        align-items: center
        justify-content: center
        &:hover
            span
                color: rgba(0, 0, 0, 0.5)
                mix-blend-mode: color-burn

.sample
    transition: 200ms all ease-in-out
    font-family: 'Prompt'
    font-size: 16px
    color: transparent

.getGradient
    position: absolute
    bottom: 10px
    right: 10px
    box-sizing: border-box
    font-family: 'Prompt'
    outline: none
    border: 2px solid black
    border-radius: 4px
    padding: 10px
    font-size: 24px
    background-color: transparent
    mix-blend-mode: color-burn
    &:focus, &:hover
        outline: none
        cursor: pointer
        
h1
    font-family: 'Prompt'
    position: absolute
    font-size: 24px
    mix-blend-mode: color-burn
    color: black
    top: calc(50vh - 12px)
    width: 50%
    text-align: center
    z-index: 1
    text-transform: uppercase
    
.leftHeading
    left: 0
    
.rightHeading
    left: 50vw
    
.overlay
    position: absolute
    top: 0
    left: 0
    background: radial-gradient(farthest-corner at 40px 40px, #051937, #004d7a, #008793, #00bf72, #a8eb12)
    width: 100%
    height: 100vh
    z-index: 2
    display: flex
    align-items: center
    justify-content: center
    h1
        color: white
        mix-blend-mode: difference
        
.hide
    display: none !important
              
            
!

JS

              
                // Labels
const ADD_COLOR = 'Add color'
const REMOVE_COLOR = 'Remove color'
const CLEAR_COLORS = 'Clear colors'
const SAMPLES = 'Samples'
const INTERPOLATION = 'Interpolation'
const MODE = 'Mode'
const LIGHTNESS_CORRECTION = 'Lightness correction'
const CSS_GRADIENT_TYPE = 'Css gradient type'
const POSITION = 'Position'
const TOP = 'Top'
const LEFT = 'Left'
const SHAPE = 'Shape'
const EXTENT_KEYWORD = 'Extent keyword'
const WITH_ANGLE = 'With angle'
const ANGLE = 'Angle'

const left = document.querySelector('.left')
const right = document.querySelector('.right')
const overlay = document.querySelector('.overlay')
const getGradient = document.querySelector('.getGradient')

// Handling the palette
const DEFAULT_COLOR = '#fcefa2'

let INDEX = 0
let MAX_INDEX = 4

const settingsPanel = QuickSettings
    .create(10, 10, 'Settings (double click to close)')
    .addButton(ADD_COLOR, () => addColor())
    .addButton(REMOVE_COLOR, () => removeColor())
    .addButton(CLEAR_COLORS, () => clearColors())
    

const addColor = () => {
    if (INDEX < MAX_INDEX) {
        INDEX++
        settingsPanel
            .addColor(`color_${INDEX}`, DEFAULT_COLOR)
    }
}

const removeColor = () => {
    if (INDEX > 0) {
        settingsPanel
            .removeControl(`color_${INDEX}`)
        INDEX--
    }
}

const clearColors = () => {
    if (INDEX > 0) {
        let colorName = /color_[0-9]/
        let colorControls = Object
            .entries(settingsPanel._controls)
            .filter(entry => {
                if (colorName.test(entry[0])) {
                    return entry
                }
            })
            .map(entry => entry[0])
        colorControls.forEach(control => {
            settingsPanel.removeControl(control)
        })
        INDEX = 0
    }
}

// handling chroma.js & css configuration
settingsPanel
    .addRange(SAMPLES, 10, 40, 10, 10)
    .addDropDown(INTERPOLATION, ['linear', 'bezier'])
    .addDropDown(MODE, ['none', 'lab', 'lch', 'lrgb', 'hsl'])
    .addBoolean(LIGHTNESS_CORRECTION, false)
    .addDropDown(CSS_GRADIENT_TYPE, ['linear', 'radial'])
    .addBoolean(POSITION, false)
    .addRange(TOP, 1, 100, 50, 1)
    .addRange(LEFT, 1, 100, 50, 1)
    .addDropDown(SHAPE, ['ellipse', 'circle'])
    .addDropDown(EXTENT_KEYWORD, ['none', 'closest-side', 'closest-corner', 'farthest-side', 'farthest-corner'])
    .addBoolean(WITH_ANGLE, false)
    .addRange(ANGLE, 1, 360, 180, 1)

// rule set
const modifyRules = () => {
    let s = settingsPanel
    let interpolation = s.getValue(INTERPOLATION).value
    let cssGradientType = s.getValue(CSS_GRADIENT_TYPE).value
    let withAngle = s.getValue(WITH_ANGLE)
    let shape = s.getValue(SHAPE).value
    let extentKeyword = s.getValue(EXTENT_KEYWORD).value
    let position = s.getValue(POSITION)
    
    switch (interpolation) {
        case 'linear':
            s.showControl(MODE);
        break;
        case 'bezier':
            s.hideControl(MODE);
        break;
    }

    switch (cssGradientType) {
        case 'linear':
            s.showControl(WITH_ANGLE)
            s.hideControl(SHAPE)
            s.hideControl(EXTENT_KEYWORD)
            s.hideControl(POSITION)
            s.hideControl(TOP)
            s.hideControl(LEFT)
            if (withAngle === true) {
                s.showControl(ANGLE)
            }
            if (withAngle === false) {
                s.hideControl(ANGLE)
            }
        break;
        case 'radial':
            s.hideControl(WITH_ANGLE)
            s.hideControl(ANGLE)
            s.showControl(POSITION)
            if (position === true) {
                s.showControl(TOP)
                s.showControl(LEFT)
            }
            if (position === false) {
                s.hideControl(TOP)
                s.hideControl(LEFT)
            }
            if (shape == 'circle') {
                s.hideControl(EXTENT_KEYWORD)
            }
            if (shape == 'ellipse') {
                s.showControl(EXTENT_KEYWORD)
            }
            if (extentKeyword !== 'none') {
                s.hideControl(SHAPE)
            }
            if (extentKeyword === 'none') {
                s.showControl(SHAPE)
            }
        break;
    }
    
}

// render gradients
const stringifyResults = (colors) => {
    return colors.map(color => {
        let r = Math.floor(color._rgb[0]),
            g = Math.floor(color._rgb[1]),
            b = Math.floor(color._rgb[2]),
            a = color._rgb[3]
        return `rgba(${r}, ${g}, ${b}, ${a})`
    })
}

const getEndString = result => {
    let s = settingsPanel
    let cssGradientType = s.getValue(CSS_GRADIENT_TYPE).value
    let shape = s.getValue(SHAPE).value
    let extentKeyword = s.getValue(EXTENT_KEYWORD).value
    let withAngle = s.getValue(WITH_ANGLE)
    let angle = s.getValue(ANGLE)
    let position = s.getValue(POSITION)
    let top = s.getValue(TOP)
    let left = s.getValue(LEFT)
    let endString
    let $angle = angle && withAngle && cssGradientType === 'linear' ? angle + 'deg, ' : ''
    let $shape = () => {
        if (cssGradientType === 'radial') {
            if (shape && shape !== 'ellipse' && position === false) {
                return shape + ', '
            }
            if (shape && shape !== 'ellipse' && position === true) {
                return `${shape} at ${left}% ${top}%, `
            }
            if (shape && shape === 'ellipse' && position === true && extentKeyword === 'none') {
                return `${shape} at ${left}% ${top}%, `
            }
            if (shape && shape === 'ellipse' && position === true && extentKeyword !== 'none') {
                return ''
            }
        }
        return ''
    }
    let $extent = () => {
        let afterExtent = position === true ? ` at ${left}% ${top}%, ` : ', '
        if (extentKeyword !== 'none') {
            return extentKeyword + afterExtent
        }
        return ''
    }
    endString = `${cssGradientType}-gradient(${$angle}${$shape()}${$extent()}${result})`
    
    return endString
}

const renderGradient = (result, endString, samples) => {
    while (left.firstChild) {
        if (left.firstChild.nodeName !== 'h3') {
            left.removeChild(
                left.firstChild
            )
        }
    }
    for (let i = 0; i < result.length; i++) {
        let color = result[i];
        let div = document.createElement('div')
        div.style = `background-color: ${color}; height: ${101 / samples}vh;`
        div.innerHTML = `<span class="sample">${div.style.backgroundColor}</span>`
        left.appendChild(div)
    }
    right.style.background = endString
}

const createGradient = () => {
    // get current configuration
    let s = settingsPanel
    let samples = s.getValue(SAMPLES)
    let interpolation = s.getValue(INTERPOLATION).value
    let mode = s.getValue(MODE).value
    let lightnessCorrection = s.getValue(LIGHTNESS_CORRECTION)
    let cssGradientType = s.getValue(CSS_GRADIENT_TYPE).value
    let shape = s.getValue(SHAPE).value
    let extentKeyword = s.getValue(EXTENT_KEYWORD).value
    let withAngle = s.getValue(WITH_ANGLE)
    let angle = s.getValue(ANGLE)
    let position = s.getValue(POSITION)
    let top = s.getValue(TOP)
    let left = s.getValue(LEFT)

    let colors = Object
        .keys(s._controls)
        .filter(entry => /color_[0-9]/.test(entry) === true)
        .map(entry => s.getValue(entry))

    let scale
    let result = []
    let endString
    
    // set scale
    switch (interpolation) {
        case 'linear':
            if (mode !== 'none') {
                if (lightnessCorrection) {
                    scale = chroma
                        .scale(colors)
                        .mode(mode)
                        .correctLightness()
                } else {
                    scale = chroma
                        .scale(colors)
                        .mode(mode)
                }
            } else {
                if (lightnessCorrection) {
                    scale = chroma
                        .scale(colors)
                        .correctLightness()
                } else {
                    scale = chroma
                        .scale(colors)
                }
            }
        break
        case 'bezier':
                if (lightnessCorrection) {
                    scale = chroma
                        .bezier(colors)
                        .scale()
                        .correctLightness()
                } else {
                    scale = chroma
                        .bezier(colors)
                }
        break
    }
    
    for (let i = 0; i < samples; i++) {
        result.push(scale(i / samples));
    }
    
    // create base gradient
    result = stringifyResults(result)
    // and the css one
    endString = getEndString(result)
    // render both
    renderGradient(result, endString, samples)
}

settingsPanel
    .setGlobalChangeHandler(() => {
        modifyRules()
        if (INDEX >= 2) {
            overlay.classList.add('hide')
            createGradient()
        } 
        if (INDEX < 2) {
            overlay.classList.remove('hide')
        }
    })

modifyRules()

//get css gradient
const showGradient = () => {
    getGradient.addEventListener('click', () => {
        let style = right.style
        document.execCommand('Copy')
        alert(style.background)
    })
}

showGradient()
              
            
!
999px

Console