css gradient maker
@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
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/435311/quicksettings.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/1.3.5/chroma.min.js"></script>
// 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()
.app
.left
.right
button.getGradient Get CSS
h1.leftHeading Base
h1.rightHeading Css
.overlay
h1 Add 2+ colors to create a gradient
Uses chroma.js for generating a gradient and modified (pull request waits for approve) QuickSettings.js.
A Pen by HARUN PEHLİVAN on CodePen.