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 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.
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.
If the stylesheet 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 CSS 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.
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.
<input type="text" id="hidden" />
<main>
<form id="color-blend-form">
<section>
<fieldset>
<label for="color1">From</label>
<input id="color1" type="color" value="#0000ff">
<span id="color1-span">#0000ff</span>
</fieldset>
<fieldset>
<label for="color2">To</label>
<input id="color2" type="color" value="#ff0000">
<span id="color2-span">#ff0000</span>
</fieldset>
<fieldset>
<label for="midpoints">Midpoints</label>
<input id="midpoints" type="number" value="1" min="1" max="50">
</fieldset>
</section>
</form>
<section id="output" class="placeholder-text">
<h1>Colour blender</h1>
<p>Select two colours and the number of midpoints to create a series of intermediately blended colours.</p>
</section>
<section class="copy">
<button id="copy-array">Copy as array</button>
</section>
</main>
$input-height: 3rem;
$padding: 1rem;
$border-color: gainsboro;
$border-radius: 2px;
$font-size: 0.75rem;
$font-color: #222;
$row-content-height: 2rem;
// quick and dirty reset
* {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0;
}
body {
font: {
family: Poppins, sans-serif;
size: $font-size;
}
color: $font-color;
}
section {
max-width: 40rem;
margin: #{$padding * 2} auto;
padding: {
right: $padding;
left: $padding;
}
}
#color-blend-form {
display: block;
background-color: white;
border: 1px solid transparent;
box-shadow: 0 0 14px rgba(black, 0.3);
section {
display: flex;
> * {
flex: 1;
display: block;
padding: $padding 0;
justify-content: space-between;
& + * {
margin-left: #{$padding * 2};
}
}
input {
display: block;
width: 100%;
height: $input-height;
padding: #{$padding * 0.5};
border: 1px solid $border-color;
border-radius: $border-radius;
&[type="color"] {
padding: 0;
}
&::-webkit-color-swatch-wrapper {
padding: 0;
}
&:focus {
outline: 0;
box-shadow: 0 2px 10px rgba(black, 0.2);
}
}
}
}
.midpoint {
padding: $padding $padding $padding 0;
+ .midpoint {
border-top: 1px solid $border-color;
}
&:first-of-type,
&:last-of-type {
color: rgba($font-color, 0.4);
}
span,
p {
display: inline-block;
height: $row-content-height;
vertical-align: middle;
line-height: $row-content-height;
}
span {
width: #{$row-content-height * 2};
margin-right: $padding;
border-radius: 2px;
}
}
// for copying to clipboard
#hidden {
position: fixed;
top: -10000px;
}
#copy-array {
padding: 0.5rem 1rem;
border-radius: 2px;
background-color: #292326;
color: white;
text-transform: uppercase;
&:focus {
outline: 0;
}
}
.placeholder-text ~ .copy {
display: none;
}
console.clear();
var col = {
/** @function _stripHash
@private
removes any leading hash tag (#) from a string
@param {string} hex - colour
@returns {string}
*/
_stripHash: function(hex) {
return (hex.substr(0, 1) === '#') ? hex.substr(1) : hex;
},
/** @function _containsValidHexChars
@private
checks that a string contains only characters
valid for a hexadecimal colour code (excluding #)
@param {string} hex - candidate for testing as valid hex colour
@returns {bool}
*/
_containsValidHexChars: function(hex) {
return (/^[0-9a-f]+$/i.test(hex));
},
/** @function _padWith0
@private
adds leading 0s if a string is shorter than 6 characters
(it assumes a number has originally been entered with leading 0s
that have been stripped away)
@param {string} hex
@returns {string}
*/
_padWith0: function(hex) {
return '000000'.substr(0, 6 - hex.length) + hex;
},
/** @function _expandHex
@private
expands a shorthand hex colour code (a03)
to a longhand (full-length) hex colour code (aa0033)
(i could have used a loop but found it pointless for six chars)
@param {string} hex - possible shorthand
@returns {string} longhand
*/
_expandHex: function(hex) {
if (hex.length === 3) {
hex.split('');
hex = [
hex[0], hex[0],
hex[1], hex[1],
hex[2], hex[2]
].join('');
}
return hex;
},
/** @function _validateHex
@private
makes sure that a usable hex colur code is being used, by
- stripping leading #
- checks for valid characters only
- expanding shorthand codes
- pads short numbers with leading 0s
- removes excess characters
if tests fails it returns hex code for black
@param {string} candidate - the string to be validates
@returns {string} valid hex code or '#000000'
@requires col._stripHash, col._containsValidHexChars, col._expandHex, col._padWith0
*/
_validateHex: function(candidate) {
var hex = col._stripHash(candidate.toString());
if (col._containsValidHexChars(hex)) {
if (hex.length === 3) {
hex = col._expandHex(hex);
} else if (hex.length < 6) {
hex = col._padWith0(hex);
} else if (hex.length > 6) {
hex = hex.substr(0, 6);
}
return hex;
}
return '000000';
},
/** @function _decimalToHex
@private
converts a decimal colour code (0-255) to hex code (00-ff)
@param {string || number} decimal
@returns {string} hex
*/
_decimalToHex: function(decimal) {
return decimal.toString(16);
},
/** @function _hexToDecimal
@private
converts a hex code (00-ff) to decimal colour code (0-255)
@param {string} hex
@returns {number} decimal
*/
_hexToDecimal: function(hex) {
return parseInt(hex, 16);
},
/** @function mix
@public
mixes two colours based on the weight specified
@author based on https://gist.github.com/jedfoster/7939513
@param {string} color1 - the first hex colour to be mixed
@param {string} color2 - the second hex colour to be mixed
@param {number} weight - the weight of colour1 used in the mix
@returns {string} hex code of colour mix
@requires col._validateHex, col._hexToDecimal, col._decimalToHex
@example
// returns '#7f007f'
col.mix('#00f', '#f00')
// returns '#69006f'
col.mix('#d300de', '#000', 75)
*/
mix: function(color1, color2, weight) {
// make sure the colors are 6 digit hex colors without leading #
color1 = col._validateHex(color1);
color2 = col._validateHex(color2);
// if weight hasn't been set (undefined)
// or outside allowed range (0-100)
// well make it 50 (an equal mix of both colors)
weight = (typeof(weight) === 'undefined' || parseInt(weight) < 0 || parseInt(weight) > 100) ? 50 : weight;
// holding variable for new colour
var newColor = '';
// loop through hex
// we want to extract each of the colour triplets (rr, gg, bb)
// so we use a step of 2
for (var i = 0; i < 6; i += 2) {
// retrieve individual color triplet
// and convert to decimal
var color1triplet = col._hexToDecimal(color1.substr(i, 2));
var color2triplet = col._hexToDecimal(color2.substr(i, 2));
// blend colour triplets
var calculatedTriplet = Math.floor(color1triplet + ((color2triplet - color1triplet) * (weight / 100)));
// convert decimal back to hex
calculatedTriplet = col._decimalToHex(calculatedTriplet);
// if only one digit prepend with 0
// and add to newColor variable
newColor += (calculatedTriplet.length === 1) ? '0' + calculatedTriplet : calculatedTriplet;
}
return '#' + newColor;
},
/** @function blendRange
@public
creates an array of colours from two colours with a requested number of midpoints
the array contains the original two colours
@param {string} color1 - the first hex colour to be mixed
@param {string} color2 - the second hex colour to be mixed
@param {number} midpoints - number of intermediate colours to be created
@returns {array} intermediate colours' hex codes bookended by the original colours
@requires col._validateHex, col.mix
*/
blendRange: function(color1, color2, midpoints) {
// make sure the colors are 6 digit hex colors without leading #
color1 = col._validateHex(color1);
color2 = col._validateHex(color2);
// make sure that the number of midpoints is bigger than 0
// and add 1 because we want to include the original colours
midpoints = (parseInt(midpoints) >= 1) ? parseInt(midpoints) + 1 : 2
// create array for the blended colours
var blendArray = [];
// loop through number of midpoints
for (var i = 0, len = midpoints; i < (len + 1); i++) {
// mix the two colours with a weight calculated on the position in the blend
// and add to blendArray
blendArray.push(col.mix(color1, color2, (100/len) * i));
}
// ... and ship back
return blendArray;
}
};
// --------------------------------------
// ui stuff:
document.querySelector('#color-blend-form').addEventListener('change', function() {
// get references
var color1 = document.querySelector('#color1').value;
var color2 = document.querySelector('#color2').value;
var color1span = document.querySelector('#color1-span');
var color2span = document.querySelector('#color2-span');
var midpoints = parseInt(document.querySelector('#midpoints').value);
var output = document.querySelector('#output');
// stuff required for adding to clipboard
var hiddenInput = document.querySelector('#hidden');
// write the hex code of the selected colours in the spans
// below the colour inputs
color1span.textContent = color1;
color2span.textContent = color2;
// create the array of mixed colours
var mix = col.blendRange(color1, color2, midpoints);
// nastily clear the output area
output.innerHTML = '';
// loop through the array of mixed colours
for (var i = 0, len = mix.length; i < len; i++) {
// create a new div for each colour
// this contains
// - a span to show the colour
// - the hex code of the colour
var colDiv = document.createElement('div');
colDiv.innerHTML = '<span style="background-color: ' + mix[i] + ';"><\/span><p>' + mix[i] + '<\/p>';
colDiv.classList.add('midpoint');
// output it
output.appendChild(colDiv);
}
// remove placeholder class to reveal button
output.classList.remove('placeholder-text');
// add it to our hidden input so we can copy it
hidden.value = mix;
}, false);
document.querySelector('#copy-array').addEventListener('click', function() {
// get hidden input value
document.querySelector('#hidden').select();
try {
var success = document.execCommand('copy');
alert(success ? 'Colours copied as array.' : 'Unable to copy.');
} catch (err) {
alert('Unable to copy.');
}
}, false);
Also see: Tab Triggers