Add extractor and builder
Tested and working
2
.gitignore
vendored
@ -2,3 +2,5 @@ node_modules/
|
|||||||
.cache/
|
.cache/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
dist/
|
dist/
|
||||||
|
src_o/
|
||||||
|
|
||||||
|
|||||||
18
config.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module.exports = {
|
||||||
|
// Project metadata
|
||||||
|
name: `30 seconds of CSS`,
|
||||||
|
description: `A curated collection of useful CSS snippets you can understand in 30 seconds or less.`,
|
||||||
|
shortName: `30s`,
|
||||||
|
repositoryUrl: `https://github.com/30-seconds/30-seconds-of-css`,
|
||||||
|
siteUrl: `https://css.30secondsofcode.org`,
|
||||||
|
// Path information
|
||||||
|
snippetPath: `snippets`,
|
||||||
|
snippetDataPath: `snippet_data`,
|
||||||
|
assetPath: `assets`,
|
||||||
|
pagePath: `src/docs/pages`,
|
||||||
|
staticPartsPath: `src/static-parts`,
|
||||||
|
// General information
|
||||||
|
language: `css`,
|
||||||
|
secondLanguage: `html`,
|
||||||
|
optionalLanguage: `js`,
|
||||||
|
};
|
||||||
|
Before Width: | Height: | Size: 255 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
773
docs/index.html
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 400 KiB |
23084
package-lock.json
generated
67
package.json
@ -4,10 +4,12 @@
|
|||||||
"description": "A curated collection of useful CSS snippets.",
|
"description": "A curated collection of useful CSS snippets.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nodemon -e md,js ./scripts/build.js & parcel index.html",
|
"builder": "node ./scripts/build.js",
|
||||||
"build": "node ./scripts/build.js && npm run prettier && npm run parcel",
|
"webber": "gatsby build",
|
||||||
"parcel": "npx rimraf docs && parcel build index.html -d docs/ --public-url ./",
|
"webber:dev": "gatsby develop",
|
||||||
"prettier": "prettier --write \"**/*.{js,json,md,css,scss}\""
|
"webber:serve": "gatsby serve",
|
||||||
|
"extractor": "node ./scripts/extract.js",
|
||||||
|
"linter": "prettier --write \"**/*.{js,json,md,css,scss}\""
|
||||||
},
|
},
|
||||||
"author": "atomiks",
|
"author": "atomiks",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -17,22 +19,47 @@
|
|||||||
"singleQuote": true
|
"singleQuote": true
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-cli": "^6.26.0",
|
"@babel/plugin-proposal-class-properties": "^7.5.0",
|
||||||
"babel-core": "^6.26.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||||
"babel-preset-env": "^1.6.1",
|
"@babel/preset-env": "^7.5.4",
|
||||||
"babel-preset-stage-2": "^6.24.1",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"caniuse-db": "^1.0.30000813",
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
|
||||||
"date-fns": "^1.29.0",
|
"caniuse-db": "^1.0.30000989",
|
||||||
"jsdom": "^11.6.2",
|
"front-matter": "^3.0.2",
|
||||||
"marked": "^0.3.16",
|
"fs-extra": "^8.1.0",
|
||||||
"node-sass": "^4.9.3",
|
"gatsby": "^2.12.0",
|
||||||
"nodemon": "^1.18.4",
|
"gatsby-image": "^2.2.6",
|
||||||
"normalize.css": "^8.0.0",
|
"gatsby-plugin-google-analytics": "^2.1.6",
|
||||||
"parcel-bundler": "^1.11.0",
|
"gatsby-plugin-manifest": "^2.2.3",
|
||||||
"prettier": "^1.14.3",
|
"gatsby-plugin-netlify": "^2.1.3",
|
||||||
"pretty": "^2.0.0",
|
"gatsby-plugin-offline": "^2.2.4",
|
||||||
"prismjs": "^1.11.0",
|
"gatsby-plugin-page-creator": "^2.1.5",
|
||||||
"rimraf": "^2.6.2"
|
"gatsby-plugin-react-helmet": "^3.1.2",
|
||||||
|
"gatsby-plugin-sass": "^2.1.3",
|
||||||
|
"gatsby-plugin-sharp": "^2.2.7",
|
||||||
|
"gatsby-plugin-sitemap": "^2.2.8",
|
||||||
|
"gatsby-plugin-transition-link": "^1.12.4",
|
||||||
|
"gatsby-remark-copy-linked-files": "^2.1.3",
|
||||||
|
"gatsby-remark-images": "^3.1.6",
|
||||||
|
"gatsby-remark-prismjs": "^3.3.3",
|
||||||
|
"gatsby-source-filesystem": "^2.1.5",
|
||||||
|
"gatsby-transformer-json": "^2.2.2",
|
||||||
|
"gatsby-transformer-remark": "^2.6.6",
|
||||||
|
"gatsby-transformer-sharp": "^2.2.3",
|
||||||
|
"gsap": "^2.1.3",
|
||||||
|
"kleur": "^3.0.3",
|
||||||
|
"markdown-builder": "^0.9.0",
|
||||||
|
"node-sass": "^4.12.0",
|
||||||
|
"prettier": "^1.18.2",
|
||||||
|
"prismjs": "^1.16.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react": "^16.8.6",
|
||||||
|
"react-copy-to-clipboard": "^5.0.1",
|
||||||
|
"react-css-transition-replace": "^3.0.3",
|
||||||
|
"react-dom": "^16.8.6",
|
||||||
|
"react-helmet": "^5.2.1",
|
||||||
|
"react-redux": "^7.1.0",
|
||||||
|
"redux": "^4.0.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"feather-icons": "^4.7.0",
|
"feather-icons": "^4.7.0",
|
||||||
|
|||||||
291
scripts/build.js
@ -1,177 +1,142 @@
|
|||||||
const fs = require('fs')
|
/*
|
||||||
const path = require('path')
|
This is the builder script that generates the README file.
|
||||||
const marked = require('marked')
|
Run using `npm run builder`.
|
||||||
const pretty = require('pretty')
|
*/
|
||||||
const caniuseDb = require('caniuse-db/data.json')
|
// Load modules
|
||||||
const sass = require('node-sass')
|
const fs = require('fs-extra');
|
||||||
const { toKebabCase, createElement, template, dom, getCode } = require('../utils/utils.js')
|
const path = require('path');
|
||||||
const { differenceInDays } = require('date-fns')
|
const { green, red } = require('kleur');
|
||||||
|
const util = require('./util');
|
||||||
|
const markdown = require('markdown-builder');
|
||||||
|
const { headers, misc, lists } = markdown;
|
||||||
|
const config = require('../config');
|
||||||
|
|
||||||
const SNIPPETS_PATH = './snippets'
|
// Paths (relative to package.json)
|
||||||
const TAGS = [
|
const SNIPPETS_PATH = `./${config.snippetPath}`;
|
||||||
{
|
const STATIC_PARTS_PATH = `./${config.staticPartsPath}`;
|
||||||
name: 'all',
|
|
||||||
icon: 'check'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'layout',
|
|
||||||
icon: 'layout'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'visual',
|
|
||||||
icon: 'eye'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'animation',
|
|
||||||
icon: 'loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'interactivity',
|
|
||||||
icon: 'edit-2'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'other',
|
|
||||||
icon: 'tag'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const renderer = new marked.Renderer()
|
// Terminate if parent commit is a Travis build
|
||||||
renderer.heading = (text, level) => {
|
if (
|
||||||
if (level === 3) {
|
util.isTravisCI() &&
|
||||||
return `<h${level} id="${toKebabCase(text)}"><span>${text}</span></h${level}>`
|
/^Travis build: \d+/g.test(process.env['TRAVIS_COMMIT_MESSAGE'])
|
||||||
} else {
|
) {
|
||||||
return ['HTML', 'CSS', 'JavaScript'].includes(text)
|
console.log(
|
||||||
? `<h${level} data-type="${text}">${text}</h${level}>`
|
`${green(
|
||||||
: `<h${level}>${text}</h${level}>`
|
'NOBUILD',
|
||||||
}
|
)} README build terminated, parent commit is a Travis build!`,
|
||||||
}
|
);
|
||||||
renderer.link = (url, _, text) => `<a href="${url}" target="_blank">${text || url}</a>`
|
process.exit(0);
|
||||||
|
|
||||||
const document = dom('./src/html/index.html')
|
|
||||||
const components = {
|
|
||||||
backToTopButton: dom('./src/html/components/back-to-top-button.html'),
|
|
||||||
sidebar: dom('./src/html/components/sidebar.html'),
|
|
||||||
header: dom('./src/html/components/header.html'),
|
|
||||||
main: dom('./src/html/components/main.html'),
|
|
||||||
tags: dom('./src/html/components/tags.html')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const snippetContainer = components.main.querySelector('.container')
|
// Setup everything
|
||||||
const sidebarLinkContainer = components.sidebar.querySelector('.sidebar__links')
|
let snippets = {},
|
||||||
TAGS.slice(1).forEach(tag => {
|
snippetsArray = [],
|
||||||
sidebarLinkContainer.append(
|
startPart = '',
|
||||||
createElement(`
|
endPart = '',
|
||||||
<section data-type="${tag.name}" class="sidebar__section">
|
output = '';
|
||||||
<h4 class="sidebar__section-heading">${tag.name}</h4>
|
const EMOJIS = {};
|
||||||
</section>
|
|
||||||
`)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const snippetFile of fs.readdirSync(SNIPPETS_PATH)) {
|
console.time('Builder');
|
||||||
const snippetPath = path.join(SNIPPETS_PATH, snippetFile)
|
|
||||||
const snippetData = fs.readFileSync(snippetPath, 'utf8')
|
|
||||||
|
|
||||||
const html = getCode('html', snippetData).trim()
|
// Synchronously read all snippets from snippets folder and sort them as necessary (case-insensitive)
|
||||||
const css = getCode('css', snippetData)
|
snippets = util.readSnippets(SNIPPETS_PATH);
|
||||||
const scopedCSS = sass.renderSync({
|
snippetsArray = Object.keys(snippets).reduce((acc, key) => {
|
||||||
data: `[data-scope="${snippetFile}"] { ${css} }`
|
acc.push(snippets[key]);
|
||||||
})
|
return acc;
|
||||||
const js = getCode('js', snippetData)
|
}, []);
|
||||||
|
|
||||||
const demo =
|
// Load static parts for the README file
|
||||||
`<div class="snippet-demo" data-scope="${snippetFile}">${html}</div>` +
|
try {
|
||||||
`<style>${scopedCSS.css.toString()}</style>` +
|
startPart = fs.readFileSync(
|
||||||
`${js ? `<script>(function(){${js}})();</script>` : ''}`
|
path.join(STATIC_PARTS_PATH, 'README-start.md'),
|
||||||
|
'utf8',
|
||||||
const markdown = marked(snippetData, { renderer }).replace(
|
);
|
||||||
'<h4>Demo</h4>',
|
endPart = fs.readFileSync(
|
||||||
`<h4>Demo</h4>${demo}`
|
path.join(STATIC_PARTS_PATH, 'README-end.md'),
|
||||||
)
|
'utf8',
|
||||||
const snippetEl = createElement(`<div class="snippet">${markdown}</div>`)
|
);
|
||||||
snippetContainer.append(snippetEl)
|
} catch (err) {
|
||||||
|
console.log(`${red('ERROR!')} During static part loading: ${err}`);
|
||||||
// browser support usage
|
process.exit(1);
|
||||||
const featUsageShares = (snippetData.match(/https?:\/\/caniuse\.com\/#feat=.*/g) || []).map(
|
|
||||||
feat => {
|
|
||||||
const featData = caniuseDb.data[feat.match(/#feat=(.*)/)[1]]
|
|
||||||
// caniuse doesn't count "untracked" users, which makes the overall share appear much lower
|
|
||||||
// than it probably is. Most of these untracked browsers probably support these features.
|
|
||||||
// Currently it's around 5.3% untracked, so we'll use 4% as probably supporting the feature.
|
|
||||||
// Also the npm package appears to be show higher usage % than the main website, this shows
|
|
||||||
// about 0.2% lower than the main website when selecting "tracked users" (as of Feb 2019).
|
|
||||||
const UNTRACKED_PERCENT = 4
|
|
||||||
const usage = featData
|
|
||||||
? Number(featData.usage_perc_y + featData.usage_perc_a) + UNTRACKED_PERCENT
|
|
||||||
: 100
|
|
||||||
return Math.min(100, usage)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const browserSupportHeading = snippetEl.querySelector('h4:last-of-type')
|
|
||||||
browserSupportHeading.after(
|
|
||||||
createElement(`
|
|
||||||
<div>
|
|
||||||
<div class="snippet__browser-support">
|
|
||||||
${featUsageShares.length ? Math.min(...featUsageShares).toPrecision(3) : 100}%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// sidebar link
|
|
||||||
const link = createElement(
|
|
||||||
`<a class="sidebar__link" href="#${snippetFile.replace('.md', '')}">${
|
|
||||||
snippetEl.querySelector('h3').innerHTML
|
|
||||||
}</a>`
|
|
||||||
)
|
|
||||||
|
|
||||||
// new icon = less than 31 days old
|
|
||||||
const date = (snippetData.match(/<!--\s*date:\s*(.+?)-->/) || [, ''])[1]
|
|
||||||
if (date && differenceInDays(new Date(), new Date(date)) < 31) {
|
|
||||||
const newIcon = '<img alt="New" draggable="false" class="snippet__new" src="./src/img/new.svg">'
|
|
||||||
snippetEl.prepend(createElement(newIcon))
|
|
||||||
link.prepend(createElement(newIcon))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags
|
// Create the output for the README file
|
||||||
const tags = (snippetData.match(/<!--\s*tags:\s*(.+?)-->/) || [, ''])[1]
|
try {
|
||||||
.split(/,\s*/)
|
const tags = util.prepTaggedData(
|
||||||
.forEach(tag => {
|
Object.keys(snippets).reduce((acc, key) => {
|
||||||
tag = tag.trim().toLowerCase()
|
acc[key] = snippets[key].attributes.tags;
|
||||||
snippetEl
|
return acc;
|
||||||
.querySelector('h3')
|
}, {}),
|
||||||
.append(
|
);
|
||||||
createElement(
|
|
||||||
`<span class="tags__tag snippet__tag" data-type="${tag}"><i data-feather="${
|
|
||||||
TAGS.find(t => t.name === tag).icon
|
|
||||||
}"></i>${tag}</span>`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
sidebarLinkContainer.querySelector(`section[data-type="${tag}"]`).append(link)
|
output += `${startPart}\n`;
|
||||||
})
|
|
||||||
|
// Loop over tags and snippets to create the table of contents
|
||||||
|
for (const tag of tags) {
|
||||||
|
const capitalizedTag = util.capitalize(tag, true);
|
||||||
|
const taggedSnippets = snippetsArray.filter(
|
||||||
|
snippet => snippet.attributes.tags[0] === tag,
|
||||||
|
);
|
||||||
|
output += headers.h3((EMOJIS[tag] || '') + ' ' + capitalizedTag).trim();
|
||||||
|
|
||||||
|
output +=
|
||||||
|
misc.collapsible(
|
||||||
|
'View contents',
|
||||||
|
lists.ul(taggedSnippets, snippet =>
|
||||||
|
misc.link(
|
||||||
|
`\`${snippet.title}\``,
|
||||||
|
`${misc.anchor(snippet.title)}${
|
||||||
|
snippet.attributes.tags.includes('advanced') ? '-' : ''
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
// build dom
|
for (const tag of tags) {
|
||||||
TAGS.forEach(tag =>
|
const capitalizedTag = util.capitalize(tag, true);
|
||||||
components.tags.append(
|
const taggedSnippets = snippetsArray.filter(
|
||||||
createElement(
|
snippet => snippet.attributes.tags[0] === tag,
|
||||||
`<button class="tags__tag is-large ${tag.name === 'all' ? 'is-active' : ''}" data-type="${
|
);
|
||||||
tag.name
|
|
||||||
}"><i data-feather="${tag.icon}"></i>${tag.name}</button>`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
const content = document.querySelector('.content-wrapper')
|
|
||||||
content.before(components.backToTopButton)
|
|
||||||
content.before(components.sidebar)
|
|
||||||
content.append(components.header)
|
|
||||||
content.append(components.main)
|
|
||||||
components.main.querySelector('.container').prepend(components.tags)
|
|
||||||
|
|
||||||
// doctype declaration gets stripped, add it back in
|
output +=
|
||||||
const html = `<!DOCTYPE html>
|
misc.hr() + headers.h2((EMOJIS[tag] || '') + ' ' + capitalizedTag) + '\n';
|
||||||
${pretty(document.documentElement.outerHTML, { ocd: true })}
|
|
||||||
`
|
|
||||||
|
|
||||||
fs.writeFileSync('./index.html', html)
|
for (let snippet of taggedSnippets) {
|
||||||
|
if (snippet.attributes.tags.includes('advanced'))
|
||||||
|
output +=
|
||||||
|
headers.h3(
|
||||||
|
snippet.title + ' ' + misc.image('advanced', '/advanced.svg'),
|
||||||
|
) + '\n';
|
||||||
|
else output += headers.h3(snippet.title) + '\n';
|
||||||
|
|
||||||
|
output += snippet.attributes.text;
|
||||||
|
|
||||||
|
output += `\`\`\`${config.secondLanguage}\n${snippet.attributes.codeBlocks.html}\n\`\`\`\n\n`;
|
||||||
|
output += `\`\`\`${config.language}\n${snippet.attributes.codeBlocks.css}\n\`\`\`\n\n`;
|
||||||
|
if (snippet.attributes.codeBlocks.js)
|
||||||
|
output += `\`\`\`${config.optionalLanguage}\n${snippet.attributes.codeBlocks.js}\n\`\`\`\n\n`;
|
||||||
|
|
||||||
|
output += headers.h4('Explanation');
|
||||||
|
output += snippet.attributes.explanation;
|
||||||
|
|
||||||
|
output += headers.h4('Browser support') + '\n';
|
||||||
|
output += snippet.attributes.browserSupport.supportPercentage.toFixed(1) + '%';
|
||||||
|
output += snippet.attributes.browserSupport.text;
|
||||||
|
|
||||||
|
output +=
|
||||||
|
'\n<br>' + misc.link('⬆ Back to top', misc.anchor('Contents')) + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the ending static part
|
||||||
|
output += `\n${endPart}\n`;
|
||||||
|
// Write to the README file
|
||||||
|
fs.writeFileSync('README.md', output);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`${red('ERROR!')} During README generation: ${err}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`${green('SUCCESS!')} README file generated!`);
|
||||||
|
console.timeEnd('Builder');
|
||||||
|
|||||||
80
scripts/extract.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
This is the extractor script that generates the snippets.json file.
|
||||||
|
Run using `npm run extractor`.
|
||||||
|
*/
|
||||||
|
// Load modules
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const path = require('path');
|
||||||
|
const { green } = require('kleur');
|
||||||
|
const util = require('./util');
|
||||||
|
const config = require('../config');
|
||||||
|
|
||||||
|
// Paths (relative to package.json)
|
||||||
|
const SNIPPETS_PATH = `./${config.snippetPath}`;
|
||||||
|
const OUTPUT_PATH = `./${config.snippetDataPath}`;
|
||||||
|
|
||||||
|
// Check if running on Travis, only build for cron jobs and custom builds
|
||||||
|
if (
|
||||||
|
util.isTravisCI() &&
|
||||||
|
process.env['TRAVIS_EVENT_TYPE'] !== 'cron' &&
|
||||||
|
process.env['TRAVIS_EVENT_TYPE'] !== 'api'
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
`${green(
|
||||||
|
'NOBUILD',
|
||||||
|
)} snippet extraction terminated, not a cron or api build!`,
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup everything
|
||||||
|
let snippets = {},
|
||||||
|
snippetsArray = [];
|
||||||
|
console.time('Extractor');
|
||||||
|
|
||||||
|
// Synchronously read all snippets from snippets folder and sort them as necessary (case-insensitive)
|
||||||
|
snippets = util.readSnippets(SNIPPETS_PATH);
|
||||||
|
snippetsArray = Object.keys(snippets).reduce((acc, key) => {
|
||||||
|
acc.push(snippets[key]);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const completeData = {
|
||||||
|
data: [...snippetsArray],
|
||||||
|
meta: {
|
||||||
|
specification: 'http://jsonapi.org/format/',
|
||||||
|
type: 'snippetArray',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let listingData = {
|
||||||
|
data: completeData.data.map(v => ({
|
||||||
|
id: v.id,
|
||||||
|
type: 'snippetListing',
|
||||||
|
title: v.title,
|
||||||
|
attributes: {
|
||||||
|
text: v.attributes.text,
|
||||||
|
tags: v.attributes.tags,
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
hash: v.meta.hash,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
meta: {
|
||||||
|
specification: 'http://jsonapi.org/format/',
|
||||||
|
type: 'snippetListingArray',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Write files
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(OUTPUT_PATH, 'snippets.json'),
|
||||||
|
JSON.stringify(completeData, null, 2),
|
||||||
|
);
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(OUTPUT_PATH, 'snippetList.json'),
|
||||||
|
JSON.stringify(listingData, null, 2),
|
||||||
|
);
|
||||||
|
// Display messages and time
|
||||||
|
console.log(
|
||||||
|
`${green('SUCCESS!')} snippets.json and snippetList.json files generated!`,
|
||||||
|
);
|
||||||
|
console.timeEnd('Extractor');
|
||||||
12
scripts/util/environmentCheck.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Checks if current environment is Travis CI, Cron builds, API builds
|
||||||
|
const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
|
||||||
|
const isTravisCronOrAPI = () =>
|
||||||
|
process.env['TRAVIS_EVENT_TYPE'] === 'cron' ||
|
||||||
|
process.env['TRAVIS_EVENT_TYPE'] === 'api';
|
||||||
|
const isNotTravisCronOrAPI = () => !isTravisCronOrAPI();
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isTravisCI,
|
||||||
|
isTravisCronOrAPI,
|
||||||
|
isNotTravisCronOrAPI,
|
||||||
|
};
|
||||||
60
scripts/util/helpers.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
const config = require('../../config');
|
||||||
|
|
||||||
|
const getMarkDownAnchor = paragraphTitle =>
|
||||||
|
paragraphTitle
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^\w\- ]+/g, '')
|
||||||
|
.replace(/\s/g, '-')
|
||||||
|
.replace(/\-+$/, '');
|
||||||
|
// Creates an object from pairs
|
||||||
|
const objectFromPairs = arr => arr.reduce((a, v) => ((a[v[0]] = v[1]), a), {});
|
||||||
|
// Optimizes nodes in an HTML document
|
||||||
|
const optimizeNodes = (data, regexp, replacer) => {
|
||||||
|
let count = 0;
|
||||||
|
let output = data;
|
||||||
|
do {
|
||||||
|
output = output.replace(regexp, replacer);
|
||||||
|
count = 0;
|
||||||
|
while (regexp.exec(output) !== null) ++count;
|
||||||
|
} while (count > 0);
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
// Capitalizes the first letter of a string
|
||||||
|
const capitalize = (str, lowerRest = false) =>
|
||||||
|
str.slice(0, 1).toUpperCase() +
|
||||||
|
(lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
|
||||||
|
const prepTaggedData = tagDbData =>
|
||||||
|
[...new Set(Object.entries(tagDbData).map(t => t[1][0]))]
|
||||||
|
.filter(v => v)
|
||||||
|
.sort((a, b) =>
|
||||||
|
capitalize(a, true) === 'Uncategorized'
|
||||||
|
? 1
|
||||||
|
: capitalize(b, true) === 'Uncategorized'
|
||||||
|
? -1
|
||||||
|
: a.localeCompare(b),
|
||||||
|
);
|
||||||
|
const makeExamples = data => {
|
||||||
|
data =
|
||||||
|
data.slice(0, data.lastIndexOf(`\`\`\`${config.language}`)).trim() +
|
||||||
|
misc.collapsible(
|
||||||
|
'Examples',
|
||||||
|
data.slice(
|
||||||
|
data.lastIndexOf(`\`\`\`${config.language}`),
|
||||||
|
data.lastIndexOf('```'),
|
||||||
|
) + data.slice(data.lastIndexOf('```')),
|
||||||
|
);
|
||||||
|
return `${data}\n<br>${misc.link(
|
||||||
|
'⬆ Back to top',
|
||||||
|
misc.anchor('Contents'),
|
||||||
|
)}\n\n`;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getMarkDownAnchor,
|
||||||
|
objectFromPairs,
|
||||||
|
optimizeNodes,
|
||||||
|
capitalize,
|
||||||
|
prepTaggedData,
|
||||||
|
makeExamples,
|
||||||
|
};
|
||||||
37
scripts/util/index.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const {
|
||||||
|
isTravisCI,
|
||||||
|
isTravisCronOrAPI,
|
||||||
|
isNotTravisCronOrAPI,
|
||||||
|
} = require('./environmentCheck');
|
||||||
|
const {
|
||||||
|
getMarkDownAnchor,
|
||||||
|
objectFromPairs,
|
||||||
|
optimizeNodes,
|
||||||
|
capitalize,
|
||||||
|
prepTaggedData,
|
||||||
|
makeExamples,
|
||||||
|
} = require('./helpers');
|
||||||
|
const {
|
||||||
|
getFilesInDir,
|
||||||
|
hashData,
|
||||||
|
getCodeBlocks,
|
||||||
|
getTextualContent,
|
||||||
|
readSnippets,
|
||||||
|
} = require('./snippetParser');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isTravisCI,
|
||||||
|
isTravisCronOrAPI,
|
||||||
|
isNotTravisCronOrAPI,
|
||||||
|
getMarkDownAnchor,
|
||||||
|
objectFromPairs,
|
||||||
|
optimizeNodes,
|
||||||
|
capitalize,
|
||||||
|
prepTaggedData,
|
||||||
|
makeExamples,
|
||||||
|
getFilesInDir,
|
||||||
|
hashData,
|
||||||
|
getCodeBlocks,
|
||||||
|
getTextualContent,
|
||||||
|
readSnippets,
|
||||||
|
};
|
||||||
198
scripts/util/snippetParser.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
const fs = require('fs-extra'),
|
||||||
|
path = require('path'),
|
||||||
|
{ red } = require('kleur'),
|
||||||
|
crypto = require('crypto'),
|
||||||
|
frontmatter = require('front-matter');
|
||||||
|
const sass = require('node-sass');
|
||||||
|
const caniuseDb = require('caniuse-db/data.json');
|
||||||
|
const config = require('../../config');
|
||||||
|
|
||||||
|
// Reade all files in a directory
|
||||||
|
const getFilesInDir = (directoryPath, withPath, exclude = null) => {
|
||||||
|
try {
|
||||||
|
let directoryFilenames = fs.readdirSync(directoryPath);
|
||||||
|
directoryFilenames.sort((a, b) => {
|
||||||
|
a = a.toLowerCase();
|
||||||
|
b = b.toLowerCase();
|
||||||
|
if (a < b) return -1;
|
||||||
|
if (a > b) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (withPath) {
|
||||||
|
// a hacky way to do conditional array.map
|
||||||
|
return directoryFilenames.reduce((fileNames, fileName) => {
|
||||||
|
if (
|
||||||
|
exclude == null ||
|
||||||
|
!exclude.some(toExclude => fileName === toExclude)
|
||||||
|
)
|
||||||
|
fileNames.push(`${directoryPath}/${fileName}`);
|
||||||
|
return fileNames;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
return directoryFilenames.filter(v => v !== 'README.md');
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`${red('ERROR!')} During snippet loading: ${err}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Creates a hash for a value using the SHA-256 algorithm.
|
||||||
|
const hashData = val =>
|
||||||
|
crypto
|
||||||
|
.createHash('sha256')
|
||||||
|
.update(val)
|
||||||
|
.digest('hex');
|
||||||
|
// Gets the code blocks for a snippet file.
|
||||||
|
const getCodeBlocks = str => {
|
||||||
|
const regex = /```[.\S\s]*?```/g;
|
||||||
|
let results = [];
|
||||||
|
let m = null;
|
||||||
|
while ((m = regex.exec(str)) !== null) {
|
||||||
|
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||||
|
|
||||||
|
m.forEach((match, groupIndex) => {
|
||||||
|
results.push(match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const replacer = new RegExp(
|
||||||
|
`\`\`\`${config.language}([\\s\\S]*?)\`\`\``,
|
||||||
|
'g',
|
||||||
|
);
|
||||||
|
const secondReplacer = new RegExp(
|
||||||
|
`\`\`\`${config.secondLanguage}([\\s\\S]*?)\`\`\``,
|
||||||
|
'g',
|
||||||
|
);
|
||||||
|
const optionalReplacer = new RegExp(
|
||||||
|
`\`\`\`${config.optionalLanguage}([\\s\\S]*?)\`\`\``,
|
||||||
|
'g',
|
||||||
|
);
|
||||||
|
results = results.map(v =>
|
||||||
|
v
|
||||||
|
.replace(replacer, '$1')
|
||||||
|
.replace(secondReplacer, '$1')
|
||||||
|
.replace(optionalReplacer, '$1')
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
|
if (results.length > 2)
|
||||||
|
return {
|
||||||
|
html: results[0],
|
||||||
|
css: results[1],
|
||||||
|
js: results[2],
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
html: results[0],
|
||||||
|
css: results[1],
|
||||||
|
js: '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Gets the textual content for a snippet file.
|
||||||
|
const getTextualContent = str => {
|
||||||
|
const regex = /([\s\S]*?)```/g;
|
||||||
|
const results = [];
|
||||||
|
let m = null;
|
||||||
|
while ((m = regex.exec(str)) !== null) {
|
||||||
|
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||||
|
|
||||||
|
m.forEach((match, groupIndex) => {
|
||||||
|
results.push(match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return results[1].replace(/\r\n/g, '\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets the explanation for a snippet file.
|
||||||
|
const getExplanation = str => {
|
||||||
|
const regex = /####\s*Explanation([\s\S]*)####/g;
|
||||||
|
const results = [];
|
||||||
|
let m = null;
|
||||||
|
while ((m = regex.exec(str)) !== null) {
|
||||||
|
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||||
|
|
||||||
|
m.forEach((match, groupIndex) => {
|
||||||
|
results.push(match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// console.log(results);
|
||||||
|
return results[1].replace(/\r\n/g, '\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets the browser support for a snippet file.
|
||||||
|
const getBrowserSupport = str => {
|
||||||
|
const regex = /####\s*Browser [s|S]upport([\s\S]*)/g;
|
||||||
|
const results = [];
|
||||||
|
let m = null;
|
||||||
|
while ((m = regex.exec(str)) !== null) {
|
||||||
|
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||||
|
|
||||||
|
m.forEach((match, groupIndex) => {
|
||||||
|
results.push(match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let browserSupportText = results[1].replace(/\r\n/g, '\n');
|
||||||
|
const supportPercentage = (browserSupportText.match(/https?:\/\/caniuse\.com\/#feat=.*/g) || []).map(
|
||||||
|
feat => {
|
||||||
|
const featData = caniuseDb.data[feat.match(/#feat=(.*)/)[1]];
|
||||||
|
// caniuse doesn't count "untracked" users, which makes the overall share appear much lower
|
||||||
|
// than it probably is. Most of these untracked browsers probably support these features.
|
||||||
|
// Currently it's around 5.3% untracked, so we'll use 4% as probably supporting the feature.
|
||||||
|
// Also the npm package appears to be show higher usage % than the main website, this shows
|
||||||
|
// about 0.2% lower than the main website when selecting "tracked users" (as of Feb 2019).
|
||||||
|
const UNTRACKED_PERCENT = 4;
|
||||||
|
const usage = featData
|
||||||
|
? Number(featData.usage_perc_y + featData.usage_perc_a) + UNTRACKED_PERCENT
|
||||||
|
: 100;
|
||||||
|
return Math.min(100, usage);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
text: browserSupportText,
|
||||||
|
supportPercentage: Math.min(...supportPercentage)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synchronously read all snippets and sort them as necessary (case-insensitive)
|
||||||
|
const readSnippets = snippetsPath => {
|
||||||
|
const snippetFilenames = getFilesInDir(snippetsPath, false);
|
||||||
|
|
||||||
|
let snippets = {};
|
||||||
|
try {
|
||||||
|
for (let snippet of snippetFilenames) {
|
||||||
|
let data = frontmatter(
|
||||||
|
fs.readFileSync(path.join(snippetsPath, snippet), 'utf8'),
|
||||||
|
);
|
||||||
|
snippets[snippet] = {
|
||||||
|
id: snippet.slice(0, -3),
|
||||||
|
title: data.attributes.title,
|
||||||
|
type: 'snippet',
|
||||||
|
attributes: {
|
||||||
|
fileName: snippet,
|
||||||
|
text: getTextualContent(data.body),
|
||||||
|
explanation: getExplanation(data.body),
|
||||||
|
browserSupport: getBrowserSupport(data.body),
|
||||||
|
codeBlocks: getCodeBlocks(data.body),
|
||||||
|
tags: data.attributes.tags.split(',').map(t => t.trim()),
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
hash: hashData(data.body),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
snippets[snippet].attributes.codeBlocks.scopedCss = sass.renderSync({
|
||||||
|
data: `[data-scope="${snippets[snippet].id}"] { ${snippets[snippet].attributes.codeBlocks.css} }`
|
||||||
|
}).css.toString();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`${red('ERROR!')} During snippet loading: ${err}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
return snippets;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getFilesInDir,
|
||||||
|
hashData,
|
||||||
|
getCodeBlocks,
|
||||||
|
getTextualContent,
|
||||||
|
getExplanation,
|
||||||
|
getBrowserSupport,
|
||||||
|
readSnippets,
|
||||||
|
};
|
||||||
704
snippet_data/snippetList.json
Normal file
@ -0,0 +1,704 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": "bouncing-loader",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Bouncing loader",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a bouncing loader animation.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "5093345481ba16eb2d9b547cc55a2ac1993c39ffe09a4c40255c9e4d9cae4cc7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "box-sizing-reset",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Box-sizing reset",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Resets the box-model so that `width`s and `height`s are not affected by their `border`s or `padding`.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "a67133bc7bf6d831340501643c7efede36b09a7f36516e0cc7fb7d3ff06ee7bd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "button-border-animation",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Button border animation",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a border animation on hover.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "754e9dc4b820bbd2f8650a06df9cf2d2e3755b0da2ae2be787bf77eb79d0e296"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "calc",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Calc()",
|
||||||
|
"attributes": {
|
||||||
|
"text": "The function calc() allows to define CSS values with the use of mathematical expressions, the value adopted for the property is the result of a mathematical expression.\n\n\n\n",
|
||||||
|
"tags": [
|
||||||
|
"other",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "fce405ede3127f068a4598d709484dae8b3991594daf5d54fbac043989d04427"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "circle",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Circle",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a circle shape with pure CSS.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "bc4bbf2fdc171fc581c72926d8b383391c1f01ccdb8853a3b4a1a290fddc704e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clearfix",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Clearfix",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Ensures that an element self-clears its children.\n\n###### Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "1047b62d1a05d21a0d5cd370eca23ca76dc52454b1aefdb4bddd83d78a624458"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "constant-width-to-height-ratio",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Constant width to height ratio",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Given an element of variable width, it will ensure its height remains proportionate in a responsive fashion\n(i.e., its width to height ratio remains constant).\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "6d9a462223d6c4d2cb83b0b3ffea991d18d5b4c2bf81881515ff07a7c49db1c8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "counter",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Counter",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Counters are, in essence, variables maintained by CSS whose values may be incremented by CSS rules to track how many times they're used.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"other",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "99ba7570de689df640c22feb4a36874d4d7bc4bd1310227cedabe55d95b83f5e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom-scrollbar",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Custom scrollbar",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Customizes the scrollbar style for the document and elements with scrollable overflow, on WebKit platforms.\n\n\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "cd46a337bd537c752499182a18575a921f300cf73b490dea2c1378360e670168"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom-text-selection",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Custom text selection",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Changes the styling of text selection.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "fa278f7299768bd484a01a9d63c7e8ba684f3870da53388aae5290d5b4dee7bb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom-variables",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Custom variables",
|
||||||
|
"attributes": {
|
||||||
|
"text": "CSS variables that contain specific values to be reused throughout a document.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"other",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "c03b24d37e43d056aa2e5f6eebb8d61a86d4d9f6587270aa8606df771c27f3cc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "disable-selection",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Disable selection",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Makes the content unselectable.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "ccae3478e0de1ff02bab055c17e2f877bd39cd4994f6b18d0bf85d16e9912dda"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "display-table-centering",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Display table centering",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Vertically and horizontally centers a child element within its parent element using `display: table` (as an alternative to `flexbox`).\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "4b2e48224b08521eda138be98210a643ff98733fed8f9dd9d1921a1f56084450"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "donut-spinner",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Donut spinner",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a donut spinner that can be used to indicate the loading of content.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "cf2af5a585eecb3c98ee07d02d2e94ebee5efdf01523313b61faa199309bee0d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dynamic-shadow",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Dynamic shadow",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a shadow similar to `box-shadow` but based on the colors of the element itself.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "125c57e66fac5a5f0f231889d6cc2bbab0c8693070254386140468ec39045556"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "easing-variables",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Easing variables",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Variables that can be reused for `transition-timing-function` properties, more\npowerful than the built-in `ease`, `ease-in`, `ease-out` and `ease-in-out`.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "742eec324f2b9eb3a5cf972639069523e1244ee95bc6335192587b8f9352f2da"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "etched-text",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Etched text",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates an effect where text appears to be \"etched\" or engraved into the background.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "fade4c04ebb8c2e6d680cc803d54738dbb166b6f608f13a94eacfe0b762fb0c4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "evenly-distributed-children",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Evenly distributed children",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Evenly distributes child elements within a parent element.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "3489ccfed45a24c536c275e7a74cc8727fd801baae9c2b5123265bcd75e70a37"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fit-image-in-container",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Fit image in container",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Changes the fit and position of an image within its container while preserving its aspect ratio. Previously only possible using a background image and the `background-size` property.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "79cb705dc7ae6fbde94fac8dc3b273dda73be7a4739a2cdf9f160ad6f678133a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flexbox-centering",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Flexbox centering",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Horizontally and vertically centers a child element within a parent element using `flexbox`.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "ec62036188c484a98e832c45535eafbf528020f116a5aac0c853b56f6b91162e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "focus-within",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Focus Within",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Changes the appearance of a form if any of its children are focused.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "db08a880101d0e82dd0263582e7b251d88450df278e7d79a0a544d1575580c55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fullscreen",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Fullscreen",
|
||||||
|
"attributes": {
|
||||||
|
"text": "The :fullscreen CSS pseudo-class represents an element that's displayed when the browser is in fullscreen mode.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "2bb108851d15d46749ba4f1caa2ba08d4754a2ee988e812280925c637f610d40"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ghost-trick",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Ghost trick",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Vertically centers an element in another.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "622cd2ec51c26b37be3ea38a55d71bbb1b5944f14188b484c4903e23b45086c9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gradient-text",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Gradient text",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Gives text a gradient color.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "56a606934b50e0c3c53eb4819ee3fcb57344a9bd7dce91ae26c6f98c99a4c386"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grid-centering",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Grid centering",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Horizontally and vertically centers a child element within a parent element using `grid`.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "167267471e09e52f20ed40ffb23b8efa1cfba6434fea5b7c82810c62c8ba5ee0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hairline-border",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Hairline border",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Gives an element a border equal to 1 native device pixel in width, which can look\nvery sharp and crisp.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "0e45709255d9ca14598c5fa54c2ae5490f81a0ef67c466d6d678da584340428b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "height-transition",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Height transition",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Transitions an element's height from `0` to `auto` when its height is unknown.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "7ee6c8c6027ccbba77e7c02bdb79cf22a0d22d7acece1ea5408da19a7f986d7a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hover-shadow-box-animation",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Hover shadow box animation",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a shadow box around the text when it is hovered.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "8fc3c2c5fc4248b2ec6bfdbc96cb5912936ccd5865d88da7a3a041a32168968a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hover-underline-animation",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Hover underline animation",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates an animated underline effect when the text is hovered over.\n\n<small>**Credit:** https://flatuicolors.com/</small>\n\n",
|
||||||
|
"tags": [
|
||||||
|
"animation",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "5ee579737769cd734df27df60b3c0fa296965192f1cdca45d4c43a414c6b9760"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "last-item-with-remaining-available-height",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Last item with remaining available height",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Take advantage of available viewport space by giving the last element the remaining available space in current viewport, even when resizing the window.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "522a5e309cea7f772600ca1d5f89ee911f0aec94b157e2adb94ac3f479445c01"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mouse-cursor-gradient-tracking",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Mouse cursor gradient tracking",
|
||||||
|
"attributes": {
|
||||||
|
"text": "A hover effect where the gradient follows the mouse cursor.\n\n<small class=\"snippet__credit\">**Credit:** [Tobias Reich](https://codepen.io/electerious/pen/MQrRxX)</small>\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "707e50fd348545fc1f9950ef9cda9e74b28ffe57098cc2849c72358c4bf7bea6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "not-selector",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": ":not selector",
|
||||||
|
"attributes": {
|
||||||
|
"text": "The `:not` psuedo selector is useful for styling a group of elements, while leaving the last (or specified) element unstyled.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "7d2727a78b8ee2a55a823116fb01099efa227952d8fba8c35a1d3067675985d5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "offscreen",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Offscreen",
|
||||||
|
"attributes": {
|
||||||
|
"text": "A bulletproof way to completely hide an element visually and positionally in the DOM while still allowing it to be accessed by JavaScript and readable by screen readers. This method is very useful for accessibility ([ADA](https://adata.org/learn-about-ada)) development when more context is needed for visually-impaired users. As an alternative to `display: none` which is not readable by screen readers or `visibility: hidden` which takes up physical space in the DOM.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "000a1fd47f9dafba64a625aefc689e33592adf69c8c5ecffb6de68a83f0218aa"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "overflow-scroll-gradient",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Overflow scroll gradient",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Adds a fading gradient to an overflowing element to better indicate there is more content to be scrolled.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "6ce90f10b574780c196faad6a498c8d5b1e5e2d6c3464ded47ceb1056b24baa3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "popout-menu",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Popout menu",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Reveals an interactive popout menu on hover and focus.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "8f5c19fb14ee8039e93ff0f3185cb0d27971dd2509f6100fdfd290478211a42b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pretty-text-underline",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Pretty text underline",
|
||||||
|
"attributes": {
|
||||||
|
"text": "A nicer alternative to `text-decoration: underline` or `<u></u>` where descenders do not clip the underline.\nNatively implemented as `text-decoration-skip-ink: auto` but it has less control over the underline.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "5d0eb22cb50d397c88c5f3a111a6a85d6cfa7d61fb7e88c966fdd55fe9d5b587"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "reset-all-styles",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Reset all styles",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Resets all styles to default values with one property. This will not affect `direction` and `unicode-bidi` properties.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "d601816311504b7521c8bba212e2c4b6fb50317ec10df60991a414bae1c82bf9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "shape-separator",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Shape separator",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Uses an SVG shape to separate two different blocks to create more a interesting visual appearance compared to standard horizontal separation.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "1ce90fc518399c775df1af832345729bdde2a3c12bbdd2fd66c40b9c57a65aa1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sibling-fade",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Sibling fade",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Fades out the siblings of a hovered item.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "a1e353f0dc466a24881986bbaf8f2cd9f367fe80d54ac8e1481d82e021236389"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system-font-stack",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "System font stack",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Uses the native font of the operating system to get close to a native app feel.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "0a35134bd1fe1da354810ef3228f50a81105997c0e81138c97cc9ace399adbb2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "toggle-switch",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Toggle switch",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a toggle switch with CSS only.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"interactivity",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "6af55186736cae8da52a2a92bf7dcf56f6f23ca49ce083ad6653e373fa2d152e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "transform-centering",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Transform centering",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Vertically and horizontally centers a child element within its parent element using `position: absolute` and `transform: translate()` (as an alternative to `flexbox` or `display: table`). Similar to `flexbox`, this method does not require you to know the height or width of your parent or child so it is ideal for responsive applications.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "67b5f73d1e7aa4850b39c461fd93a548e106569554cf6e87f2a9981ecfb77ad1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "triangle",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Triangle",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a triangle shape with pure CSS.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "d585e568bd1b8ca9c8a7d2fa52682c80249bf1e6055316bc3526ee54d8d26fb9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "truncate-text-multiline",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Truncate text multiline",
|
||||||
|
"attributes": {
|
||||||
|
"text": "If the text is longer than one line, it will be truncated for `n` lines and end with an gradient fade.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "487720c3bf69c29c26cd0033d69f7391b634c4d9bf0e72a1da29957b945a9cbf"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "truncate-text",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Truncate text",
|
||||||
|
"attributes": {
|
||||||
|
"text": "If the text is longer than one line, it will be truncated and end with an ellipsis `…`.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"layout",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "db78085f4583d992126b4ceb74cc680300aa67c16d37b68d55c140fe453840d3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zebra-striped-list",
|
||||||
|
"type": "snippetListing",
|
||||||
|
"title": "Zebra striped list",
|
||||||
|
"attributes": {
|
||||||
|
"text": "Creates a striped list with alternating background colors, which is useful for differentiating siblings that have content spread across a wide row.\n\n",
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "2c11f668918ede13c492719a76a5b89173aa4e72ad896cd2d7e45bed9671a2f0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"specification": "http://jsonapi.org/format/",
|
||||||
|
"type": "snippetListingArray"
|
||||||
|
}
|
||||||
|
}
|
||||||
1256
snippet_data/snippets.json
Normal file
@ -5,8 +5,6 @@ tags: animation,intermediate
|
|||||||
|
|
||||||
Creates a bouncing loader animation.
|
Creates a bouncing loader animation.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="bouncing-loader">
|
<div class="bouncing-loader">
|
||||||
<div></div>
|
<div></div>
|
||||||
@ -15,8 +13,6 @@ Creates a bouncing loader animation.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
@keyframes bouncing-loader {
|
@keyframes bouncing-loader {
|
||||||
to {
|
to {
|
||||||
@ -44,8 +40,6 @@ Creates a bouncing loader animation.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
Note: `1rem` is usually `16px`.
|
Note: `1rem` is usually `16px`.
|
||||||
|
|||||||
@ -5,15 +5,11 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Resets the box-model so that `width`s and `height`s are not affected by their `border`s or `padding`.
|
Resets the box-model so that `width`s and `height`s are not affected by their `border`s or `padding`.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="box">border-box</div>
|
<div class="box">border-box</div>
|
||||||
<div class="box content-box">content-box</div>
|
<div class="box content-box">content-box</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -37,8 +33,6 @@ html {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `box-sizing: border-box` makes the addition of `padding` or `border`s not affect an element's `width` or `height`.
|
1. `box-sizing: border-box` makes the addition of `padding` or `border`s not affect an element's `width` or `height`.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: animation,intermediate
|
|||||||
|
|
||||||
Creates a border animation on hover.
|
Creates a border animation on hover.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="button-border"><button class="button">Submit</button></div>
|
<div class="button-border"><button class="button">Submit</button></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.button {
|
.button {
|
||||||
background-color: #c47135;
|
background-color: #c47135;
|
||||||
@ -51,14 +47,8 @@ Creates a border animation on hover.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
Use the `:before` and `:after` pseduo-elements as borders that animate on hover.
|
Use the `:before` and `:after` pseduo-elements as borders that animate on hover.
|
||||||
|
|
||||||
#### Browser support
|
#### Browser support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- date: 2018-10-30 -->
|
|
||||||
|
|||||||
@ -5,14 +5,12 @@ tags: other,intermediate
|
|||||||
|
|
||||||
The function calc() allows to define CSS values with the use of mathematical expressions, the value adopted for the property is the result of a mathematical expression.
|
The function calc() allows to define CSS values with the use of mathematical expressions, the value adopted for the property is the result of a mathematical expression.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="box-example"></div>
|
<div class="box-example"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.box-example {
|
.box-example {
|
||||||
height: 280px;
|
height: 280px;
|
||||||
@ -21,7 +19,7 @@ The function calc() allows to define CSS values with the use of mathematical exp
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
If you want to align a background-image from right and bottom wasn't possible with just straight length values.
|
If you want to align a background-image from right and bottom wasn't possible with just straight length values.
|
||||||
So now it's possible using calc():
|
So now it's possible using calc():
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Creates a circle shape with pure CSS.
|
Creates a circle shape with pure CSS.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="circle"></div>
|
<div class="circle"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.circle {
|
.circle {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@ -22,8 +18,6 @@ Creates a circle shape with pure CSS.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`border-radius: 50%` curves the borders of an element to create a circle.
|
`border-radius: 50%` curves the borders of an element to create a circle.
|
||||||
|
|||||||
@ -7,8 +7,6 @@ Ensures that an element self-clears its children.
|
|||||||
|
|
||||||
###### Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.
|
###### Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="floated">float a</div>
|
<div class="floated">float a</div>
|
||||||
@ -17,8 +15,6 @@ Ensures that an element self-clears its children.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.clearfix::after {
|
.clearfix::after {
|
||||||
content: '';
|
content: '';
|
||||||
@ -31,8 +27,6 @@ Ensures that an element self-clears its children.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `.clearfix::after` defines a pseudo-element.
|
1. `.clearfix::after` defines a pseudo-element.
|
||||||
|
|||||||
@ -6,14 +6,10 @@ tags: layout,intermediate
|
|||||||
Given an element of variable width, it will ensure its height remains proportionate in a responsive fashion
|
Given an element of variable width, it will ensure its height remains proportionate in a responsive fashion
|
||||||
(i.e., its width to height ratio remains constant).
|
(i.e., its width to height ratio remains constant).
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="constant-width-to-height-ratio"></div>
|
<div class="constant-width-to-height-ratio"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.constant-width-to-height-ratio {
|
.constant-width-to-height-ratio {
|
||||||
background: #333;
|
background: #333;
|
||||||
@ -31,8 +27,6 @@ Given an element of variable width, it will ensure its height remains proportion
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`padding-top` on the `::before` pseudo-element causes the height of the element to equal a percentage of
|
`padding-top` on the `::before` pseudo-element causes the height of the element to equal a percentage of
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual, other,intermediate
|
|||||||
|
|
||||||
Counters are, in essence, variables maintained by CSS whose values may be incremented by CSS rules to track how many times they're used.
|
Counters are, in essence, variables maintained by CSS whose values may be incremented by CSS rules to track how many times they're used.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<ul>
|
<ul>
|
||||||
<li>List item</li>
|
<li>List item</li>
|
||||||
@ -22,8 +20,6 @@ Counters are, in essence, variables maintained by CSS whose values may be increm
|
|||||||
</ul>
|
</ul>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
ul {
|
ul {
|
||||||
counter-reset: counter;
|
counter-reset: counter;
|
||||||
@ -35,8 +31,6 @@ li::before {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
You can create a ordered list using any type of HTML.
|
You can create a ordered list using any type of HTML.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Customizes the scrollbar style for the document and elements with scrollable overflow, on WebKit platforms.
|
Customizes the scrollbar style for the document and elements with scrollable overflow, on WebKit platforms.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="custom-scrollbar">
|
<div class="custom-scrollbar">
|
||||||
@ -18,7 +18,7 @@ Customizes the scrollbar style for the document and elements with scrollable ove
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.custom-scrollbar {
|
.custom-scrollbar {
|
||||||
@ -43,7 +43,7 @@ Customizes the scrollbar style for the document and elements with scrollable ove
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Changes the styling of text selection.
|
Changes the styling of text selection.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="custom-text-selection">Select some of this text.</p>
|
<p class="custom-text-selection">Select some of this text.</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
::selection {
|
::selection {
|
||||||
background: aquamarine;
|
background: aquamarine;
|
||||||
@ -24,8 +20,6 @@ Changes the styling of text selection.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`::selection` defines a pseudo selector on an element to style text within it when selected. Note that if you don't combine any other selector your style will be applied at document root level, to any selectable element.
|
`::selection` defines a pseudo selector on an element to style text within it when selected. Note that if you don't combine any other selector your style will be applied at document root level, to any selectable element.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: other,intermediate
|
|||||||
|
|
||||||
CSS variables that contain specific values to be reused throughout a document.
|
CSS variables that contain specific values to be reused throughout a document.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="custom-variables">CSS is awesome!</p>
|
<p class="custom-variables">CSS is awesome!</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
:root {
|
:root {
|
||||||
/* Place variables within here to use the variables globally. */
|
/* Place variables within here to use the variables globally. */
|
||||||
@ -30,8 +26,6 @@ CSS variables that contain specific values to be reused throughout a document.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
The variables are defined globally within the `:root` CSS pseudo-class which matches the root element of a tree representing the document. Variables can also be scoped to a selector if defined within the block.
|
The variables are defined globally within the `:root` CSS pseudo-class which matches the root element of a tree representing the document. Variables can also be scoped to a selector if defined within the block.
|
||||||
|
|||||||
@ -5,23 +5,17 @@ tags: interactivity,intermediate
|
|||||||
|
|
||||||
Makes the content unselectable.
|
Makes the content unselectable.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p>You can select me.</p>
|
<p>You can select me.</p>
|
||||||
<p class="unselectable">You can't select me!</p>
|
<p class="unselectable">You can't select me!</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.unselectable {
|
.unselectable {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`user-select: none` specifies that the text cannot be selected.
|
`user-select: none` specifies that the text cannot be selected.
|
||||||
|
|||||||
@ -5,16 +5,12 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Vertically and horizontally centers a child element within its parent element using `display: table` (as an alternative to `flexbox`).
|
Vertically and horizontally centers a child element within its parent element using `display: table` (as an alternative to `flexbox`).
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="center"><span>Centered content</span></div>
|
<div class="center"><span>Centered content</span></div>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.container {
|
.container {
|
||||||
border: 1px solid #333;
|
border: 1px solid #333;
|
||||||
@ -35,8 +31,6 @@ Vertically and horizontally centers a child element within its parent element us
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: table` on '.center' allows the element to behave like a `<table>` HTML element.
|
1. `display: table` on '.center' allows the element to behave like a `<table>` HTML element.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: animation,intermediate
|
|||||||
|
|
||||||
Creates a donut spinner that can be used to indicate the loading of content.
|
Creates a donut spinner that can be used to indicate the loading of content.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="donut"></div>
|
<div class="donut"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
@keyframes donut-spin {
|
@keyframes donut-spin {
|
||||||
0% {
|
0% {
|
||||||
@ -33,8 +29,6 @@ Creates a donut spinner that can be used to indicate the loading of content.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
Use a semi-transparent `border` for the whole element, except one side that will
|
Use a semi-transparent `border` for the whole element, except one side that will
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Creates a shadow similar to `box-shadow` but based on the colors of the element itself.
|
Creates a shadow similar to `box-shadow` but based on the colors of the element itself.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="dynamic-shadow"></div>
|
<div class="dynamic-shadow"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.dynamic-shadow {
|
.dynamic-shadow {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -34,8 +30,6 @@ Creates a shadow similar to `box-shadow` but based on the colors of the element
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `position: relative` on the element establishes a Cartesian positioning context for psuedo-elements.
|
1. `position: relative` on the element establishes a Cartesian positioning context for psuedo-elements.
|
||||||
|
|||||||
@ -6,14 +6,10 @@ tags: animation,intermediate
|
|||||||
Variables that can be reused for `transition-timing-function` properties, more
|
Variables that can be reused for `transition-timing-function` properties, more
|
||||||
powerful than the built-in `ease`, `ease-in`, `ease-out` and `ease-in-out`.
|
powerful than the built-in `ease`, `ease-in`, `ease-out` and `ease-in-out`.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="easing-variables">Hover</div>
|
<div class="easing-variables">Hover</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
:root {
|
:root {
|
||||||
/* Place variables in here to use globally */
|
/* Place variables in here to use globally */
|
||||||
@ -56,8 +52,6 @@ powerful than the built-in `ease`, `ease-in`, `ease-out` and `ease-in-out`.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
The variables are defined globally within the `:root` CSS pseudo-class which matches the root element of a tree representing the document. In HTML, `:root` represents the `<html>` element and is identical to the selector `html`, except that its specificity is higher.
|
The variables are defined globally within the `:root` CSS pseudo-class which matches the root element of a tree representing the document. In HTML, `:root` represents the `<html>` element and is identical to the selector `html`, except that its specificity is higher.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Creates an effect where text appears to be "etched" or engraved into the background.
|
Creates an effect where text appears to be "etched" or engraved into the background.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="etched-text">I appear etched into the background.</p>
|
<p class="etched-text">I appear etched into the background.</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.etched-text {
|
.etched-text {
|
||||||
text-shadow: 0 2px white;
|
text-shadow: 0 2px white;
|
||||||
@ -22,8 +18,6 @@ Creates an effect where text appears to be "etched" or engraved into the backgro
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`text-shadow: 0 2px white` creates a white shadow offset `0px` horizontally and `2px` vertically
|
`text-shadow: 0 2px white` creates a white shadow offset `0px` horizontally and `2px` vertically
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Evenly distributes child elements within a parent element.
|
Evenly distributes child elements within a parent element.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="evenly-distributed-children">
|
<div class="evenly-distributed-children">
|
||||||
<p>Item1</p>
|
<p>Item1</p>
|
||||||
@ -15,8 +13,6 @@ Evenly distributes child elements within a parent element.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.evenly-distributed-children {
|
.evenly-distributed-children {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -24,8 +20,6 @@ Evenly distributes child elements within a parent element.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: flex` enables flexbox.
|
1. `display: flex` enables flexbox.
|
||||||
|
|||||||
@ -5,15 +5,11 @@ tags: layout, visual,intermediate
|
|||||||
|
|
||||||
Changes the fit and position of an image within its container while preserving its aspect ratio. Previously only possible using a background image and the `background-size` property.
|
Changes the fit and position of an image within its container while preserving its aspect ratio. Previously only possible using a background image and the `background-size` property.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<img class="image image-contain" src="https://picsum.photos/600/200" />
|
<img class="image image-contain" src="https://picsum.photos/600/200" />
|
||||||
<img class="image image-cover" src="https://picsum.photos/600/200" />
|
<img class="image image-cover" src="https://picsum.photos/600/200" />
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.image {
|
.image {
|
||||||
background: #34495e;
|
background: #34495e;
|
||||||
@ -33,8 +29,6 @@ Changes the fit and position of an image within its container while preserving i
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
- `object-fit: contain` fits the entire image within the container while preserving its aspect ratio.
|
- `object-fit: contain` fits the entire image within the container while preserving its aspect ratio.
|
||||||
@ -44,7 +38,3 @@ Changes the fit and position of an image within its container while preserving i
|
|||||||
#### Browser support
|
#### Browser support
|
||||||
|
|
||||||
- https://caniuse.com/#feat=object-fit
|
- https://caniuse.com/#feat=object-fit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- date: 2018-10-31 -->
|
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Horizontally and vertically centers a child element within a parent element using `flexbox`.
|
Horizontally and vertically centers a child element within a parent element using `flexbox`.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="flexbox-centering"><div class="child">Centered content.</div></div>
|
<div class="flexbox-centering"><div class="child">Centered content.</div></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.flexbox-centering {
|
.flexbox-centering {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -22,8 +18,6 @@ Horizontally and vertically centers a child element within a parent element usin
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: flex` enables flexbox.
|
1. `display: flex` enables flexbox.
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual, interactivity,intermediate
|
|||||||
|
|
||||||
Changes the appearance of a form if any of its children are focused.
|
Changes the appearance of a form if any of its children are focused.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="focus-within">
|
<div class="focus-within">
|
||||||
<form>
|
<form>
|
||||||
@ -16,8 +14,6 @@ Changes the appearance of a form if any of its children are focused.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
form {
|
form {
|
||||||
border: 3px solid #2d98da;
|
border: 3px solid #2d98da;
|
||||||
@ -31,8 +27,6 @@ form:focus-within {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
<!-- Leave this blank, the build script will generate the demo for you. -->
|
<!-- Leave this blank, the build script will generate the demo for you. -->
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
The :fullscreen CSS pseudo-class represents an element that's displayed when the browser is in fullscreen mode.
|
The :fullscreen CSS pseudo-class represents an element that's displayed when the browser is in fullscreen mode.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p><em>Click the button below to enter the element into fullscreen mode. </em></p>
|
<p><em>Click the button below to enter the element into fullscreen mode. </em></p>
|
||||||
@ -18,8 +16,6 @@ The :fullscreen CSS pseudo-class represents an element that's displayed when the
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.container {
|
.container {
|
||||||
margin: 40px auto;
|
margin: 40px auto;
|
||||||
@ -50,8 +46,6 @@ The :fullscreen CSS pseudo-class represents an element that's displayed when the
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `fullscreen` CSS pseudo-class selector is used to select and style an element that is being displayed in fullscreen mode.
|
1. `fullscreen` CSS pseudo-class selector is used to select and style an element that is being displayed in fullscreen mode.
|
||||||
|
|||||||
@ -5,16 +5,12 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Vertically centers an element in another.
|
Vertically centers an element in another.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="ghost-trick">
|
<div class="ghost-trick">
|
||||||
<div class="ghosting"><p>Vertically centered without changing the position property.</p></div>
|
<div class="ghosting"><p>Vertically centered without changing the position property.</p></div>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.ghosting {
|
.ghosting {
|
||||||
height: 300px;
|
height: 300px;
|
||||||
@ -34,8 +30,6 @@ p {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
Use the style of a `:before` pseudo-element to vertically align inline elements without changing their `position` property.
|
Use the style of a `:before` pseudo-element to vertically align inline elements without changing their `position` property.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Gives text a gradient color.
|
Gives text a gradient color.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="gradient-text">Gradient text</p>
|
<p class="gradient-text">Gradient text</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.gradient-text {
|
.gradient-text {
|
||||||
background: -webkit-linear-gradient(pink, red);
|
background: -webkit-linear-gradient(pink, red);
|
||||||
@ -21,8 +17,6 @@ Gives text a gradient color.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `background: -webkit-linear-gradient(...)` gives the text element a gradient background.
|
1. `background: -webkit-linear-gradient(...)` gives the text element a gradient background.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Horizontally and vertically centers a child element within a parent element using `grid`.
|
Horizontally and vertically centers a child element within a parent element using `grid`.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="grid-centering"><div class="child">Centered content.</div></div>
|
<div class="grid-centering"><div class="child">Centered content.</div></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.grid-centering {
|
.grid-centering {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -22,8 +18,6 @@ Horizontally and vertically centers a child element within a parent element usin
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: grid` enables grid.
|
1. `display: grid` enables grid.
|
||||||
|
|||||||
@ -6,14 +6,10 @@ tags: visual,intermediate
|
|||||||
Gives an element a border equal to 1 native device pixel in width, which can look
|
Gives an element a border equal to 1 native device pixel in width, which can look
|
||||||
very sharp and crisp.
|
very sharp and crisp.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="hairline-border">text</div>
|
<div class="hairline-border">text</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.hairline-border {
|
.hairline-border {
|
||||||
box-shadow: 0 0 0 1px;
|
box-shadow: 0 0 0 1px;
|
||||||
@ -38,8 +34,6 @@ very sharp and crisp.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `box-shadow`, when only using spread, adds a pseudo-border which can use subpixels\*.
|
1. `box-shadow`, when only using spread, adds a pseudo-border which can use subpixels\*.
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: animation,intermediate
|
|||||||
|
|
||||||
Transitions an element's height from `0` to `auto` when its height is unknown.
|
Transitions an element's height from `0` to `auto` when its height is unknown.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
Hover me to see a height transition.
|
Hover me to see a height transition.
|
||||||
@ -14,8 +12,6 @@ Transitions an element's height from `0` to `auto` when its height is unknown.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.el {
|
.el {
|
||||||
transition: max-height 0.5s;
|
transition: max-height 0.5s;
|
||||||
@ -28,28 +24,20 @@ Transitions an element's height from `0` to `auto` when its height is unknown.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### JavaScript
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var el = document.querySelector('.el')
|
var el = document.querySelector('.el')
|
||||||
var height = el.scrollHeight
|
var height = el.scrollHeight
|
||||||
el.style.setProperty('--max-height', height + 'px')
|
el.style.setProperty('--max-height', height + 'px')
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
##### CSS
|
|
||||||
|
|
||||||
1. `transition: max-height: 0.5s cubic-bezier(...)` specifies that changes to `max-height` should be transitioned over 0.5 seconds, using an `ease-out-quint` timing function.
|
1. `transition: max-height: 0.5s cubic-bezier(...)` specifies that changes to `max-height` should be transitioned over 0.5 seconds, using an `ease-out-quint` timing function.
|
||||||
2. `overflow: hidden` prevents the contents of the hidden element from overflowing its container.
|
2. `overflow: hidden` prevents the contents of the hidden element from overflowing its container.
|
||||||
3. `max-height: 0` specifies that the element has no height initially.
|
3. `max-height: 0` specifies that the element has no height initially.
|
||||||
4. `.target:hover > .el` specifies that when the parent is hovered over, target a child `.el` within
|
4. `.target:hover > .el` specifies that when the parent is hovered over, target a child `.el` within
|
||||||
it and use the `--max-height` variable which was defined by JavaScript.
|
it and use the `--max-height` variable which was defined by JavaScript.
|
||||||
|
---
|
||||||
##### JavaScript
|
|
||||||
|
|
||||||
1. `el.scrollHeight` is the height of the element including overflow, which will change dynamically
|
1. `el.scrollHeight` is the height of the element including overflow, which will change dynamically
|
||||||
based on the content of the element.
|
based on the content of the element.
|
||||||
2. `el.style.setProperty(...)` sets the `--max-height` CSS variable which is used to specify the `max-height` of the element the target is hovered over, allowing it to transition smoothly from 0 to auto.
|
2. `el.style.setProperty(...)` sets the `--max-height` CSS variable which is used to specify the `max-height` of the element the target is hovered over, allowing it to transition smoothly from 0 to auto.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: animation,intermediate
|
|||||||
|
|
||||||
Creates a shadow box around the text when it is hovered.
|
Creates a shadow box around the text when it is hovered.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="hover-shadow-box-animation">Box it!</p>
|
<p class="hover-shadow-box-animation">Box it!</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.hover-shadow-box-animation {
|
.hover-shadow-box-animation {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -31,8 +27,6 @@ Creates a shadow box around the text when it is hovered.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: inline-block` to set width and length for `p` element thus making it an `inline-block`.
|
1. `display: inline-block` to set width and length for `p` element thus making it an `inline-block`.
|
||||||
|
|||||||
@ -7,14 +7,10 @@ Creates an animated underline effect when the text is hovered over.
|
|||||||
|
|
||||||
<small>**Credit:** https://flatuicolors.com/</small>
|
<small>**Credit:** https://flatuicolors.com/</small>
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="hover-underline-animation">Hover this text to see the effect!</p>
|
<p class="hover-underline-animation">Hover this text to see the effect!</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.hover-underline-animation {
|
.hover-underline-animation {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -39,8 +35,6 @@ Creates an animated underline effect when the text is hovered over.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `display: inline-block` makes the block `p` an `inline-block` to prevent the underline from
|
1. `display: inline-block` makes the block `p` an `inline-block` to prevent the underline from
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Take advantage of available viewport space by giving the last element the remaining available space in current viewport, even when resizing the window.
|
Take advantage of available viewport space by giving the last element the remaining available space in current viewport, even when resizing the window.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div>Div 1</div>
|
<div>Div 1</div>
|
||||||
@ -15,8 +13,6 @@ Take advantage of available viewport space by giving the last element the remain
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
@ -36,8 +32,6 @@ body {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `height: 100%` set the height of container as viewport height.
|
1. `height: 100%` set the height of container as viewport height.
|
||||||
@ -52,7 +46,3 @@ The parent must have a viewport height. `flex-grow: 1` could be applied to the f
|
|||||||
<span class="snippet__support-note">⚠️ Needs prefixes for full support.</span>
|
<span class="snippet__support-note">⚠️ Needs prefixes for full support.</span>
|
||||||
|
|
||||||
- https://caniuse.com/#feat=flexbox
|
- https://caniuse.com/#feat=flexbox
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- date: 2018-09-30 -->
|
|
||||||
|
|||||||
@ -7,14 +7,10 @@ A hover effect where the gradient follows the mouse cursor.
|
|||||||
|
|
||||||
<small class="snippet__credit">**Credit:** [Tobias Reich](https://codepen.io/electerious/pen/MQrRxX)</small>
|
<small class="snippet__credit">**Credit:** [Tobias Reich](https://codepen.io/electerious/pen/MQrRxX)</small>
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<button class="mouse-cursor-gradient-tracking"><span>Hover me</span></button>
|
<button class="mouse-cursor-gradient-tracking"><span>Hover me</span></button>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.mouse-cursor-gradient-tracking {
|
.mouse-cursor-gradient-tracking {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -50,8 +46,6 @@ A hover effect where the gradient follows the mouse cursor.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### JavaScript
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var btn = document.querySelector('.mouse-cursor-gradient-tracking')
|
var btn = document.querySelector('.mouse-cursor-gradient-tracking')
|
||||||
btn.onmousemove = function(e) {
|
btn.onmousemove = function(e) {
|
||||||
@ -62,11 +56,11 @@ btn.onmousemove = function(e) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
_TODO_
|
1. `--x` and `--y` are used to track the position of the mouse on the button.
|
||||||
|
2. `--size` is used to keep modify of the gradient's dimensions.
|
||||||
|
3. `background: radial-gradient(circle closest-side, pink, transparent);` creates the gradient at the correct postion.
|
||||||
|
|
||||||
#### Browser support
|
#### Browser support
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
The `:not` psuedo selector is useful for styling a group of elements, while leaving the last (or specified) element unstyled.
|
The `:not` psuedo selector is useful for styling a group of elements, while leaving the last (or specified) element unstyled.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<ul class="css-not-selector-shortcut">
|
<ul class="css-not-selector-shortcut">
|
||||||
<li>One</li>
|
<li>One</li>
|
||||||
@ -16,8 +14,6 @@ The `:not` psuedo selector is useful for styling a group of elements, while leav
|
|||||||
</ul>
|
</ul>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.css-not-selector-shortcut {
|
.css-not-selector-shortcut {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -38,8 +34,6 @@ li:not(:last-child) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
`li:not(:last-child)` specifies that the styles should apply to all `li` elements except
|
`li:not(:last-child)` specifies that the styles should apply to all `li` elements except
|
||||||
|
|||||||
@ -5,16 +5,12 @@ tags: layout, visual,intermediate
|
|||||||
|
|
||||||
A bulletproof way to completely hide an element visually and positionally in the DOM while still allowing it to be accessed by JavaScript and readable by screen readers. This method is very useful for accessibility ([ADA](https://adata.org/learn-about-ada)) development when more context is needed for visually-impaired users. As an alternative to `display: none` which is not readable by screen readers or `visibility: hidden` which takes up physical space in the DOM.
|
A bulletproof way to completely hide an element visually and positionally in the DOM while still allowing it to be accessed by JavaScript and readable by screen readers. This method is very useful for accessibility ([ADA](https://adata.org/learn-about-ada)) development when more context is needed for visually-impaired users. As an alternative to `display: none` which is not readable by screen readers or `visibility: hidden` which takes up physical space in the DOM.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<a class="button" href="http://pantswebsite.com">
|
<a class="button" href="http://pantswebsite.com">
|
||||||
Learn More <span class="offscreen"> about pants</span>
|
Learn More <span class="offscreen"> about pants</span>
|
||||||
</a>
|
</a>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.offscreen {
|
.offscreen {
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -28,8 +24,6 @@ A bulletproof way to completely hide an element visually and positionally in the
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. Remove all borders.
|
1. Remove all borders.
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Adds a fading gradient to an overflowing element to better indicate there is more content to be scrolled.
|
Adds a fading gradient to an overflowing element to better indicate there is more content to be scrolled.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="overflow-scroll-gradient">
|
<div class="overflow-scroll-gradient">
|
||||||
<div class="overflow-scroll-gradient__scroller">
|
<div class="overflow-scroll-gradient__scroller">
|
||||||
@ -22,8 +20,6 @@ Adds a fading gradient to an overflowing element to better indicate there is mor
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.overflow-scroll-gradient {
|
.overflow-scroll-gradient {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -50,8 +46,6 @@ Adds a fading gradient to an overflowing element to better indicate there is mor
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `position: relative` on the parent establishes a Cartesian positioning context for pseudo-elements.
|
1. `position: relative` on the parent establishes a Cartesian positioning context for pseudo-elements.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: interactivity,intermediate
|
|||||||
|
|
||||||
Reveals an interactive popout menu on hover and focus.
|
Reveals an interactive popout menu on hover and focus.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="reference" tabindex="0"><div class="popout-menu">Popout menu</div></div>
|
<div class="reference" tabindex="0"><div class="popout-menu">Popout menu</div></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.reference {
|
.reference {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -35,8 +31,6 @@ Reveals an interactive popout menu on hover and focus.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `position: relative` on the reference parent establishes a Cartesian positioning context for its child.
|
1. `position: relative` on the reference parent establishes a Cartesian positioning context for its child.
|
||||||
|
|||||||
@ -6,14 +6,10 @@ tags: visual,intermediate
|
|||||||
A nicer alternative to `text-decoration: underline` or `<u></u>` where descenders do not clip the underline.
|
A nicer alternative to `text-decoration: underline` or `<u></u>` where descenders do not clip the underline.
|
||||||
Natively implemented as `text-decoration-skip-ink: auto` but it has less control over the underline.
|
Natively implemented as `text-decoration-skip-ink: auto` but it has less control over the underline.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="pretty-text-underline">Pretty text underline without clipping descending letters.</p>
|
<p class="pretty-text-underline">Pretty text underline without clipping descending letters.</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.pretty-text-underline {
|
.pretty-text-underline {
|
||||||
display: inline;
|
display: inline;
|
||||||
@ -33,8 +29,6 @@ Natively implemented as `text-decoration-skip-ink: auto` but it has less control
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `text-shadow` uses 4 values with offsets that cover a 4x4 px area to ensure the underline
|
1. `text-shadow` uses 4 values with offsets that cover a 4x4 px area to ensure the underline
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Resets all styles to default values with one property. This will not affect `direction` and `unicode-bidi` properties.
|
Resets all styles to default values with one property. This will not affect `direction` and `unicode-bidi` properties.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="reset-all-styles">
|
<div class="reset-all-styles">
|
||||||
<h5>Title</h5>
|
<h5>Title</h5>
|
||||||
@ -18,16 +16,12 @@ Resets all styles to default values with one property. This will not affect `dir
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.reset-all-styles {
|
.reset-all-styles {
|
||||||
all: initial;
|
all: initial;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
The `all` property allows you to reset all styles (inherited or not) to default values.
|
The `all` property allows you to reset all styles (inherited or not) to default values.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Uses an SVG shape to separate two different blocks to create more a interesting visual appearance compared to standard horizontal separation.
|
Uses an SVG shape to separate two different blocks to create more a interesting visual appearance compared to standard horizontal separation.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="shape-separator"></div>
|
<div class="shape-separator"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.shape-separator {
|
.shape-separator {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -29,8 +25,6 @@ Uses an SVG shape to separate two different blocks to create more a interesting
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `position: relative` on the element establishes a Cartesian positioning context for pseudo elements.
|
1. `position: relative` on the element establishes a Cartesian positioning context for pseudo elements.
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: interactivity,intermediate
|
|||||||
|
|
||||||
Fades out the siblings of a hovered item.
|
Fades out the siblings of a hovered item.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="sibling-fade">
|
<div class="sibling-fade">
|
||||||
<span>Item 1</span> <span>Item 2</span> <span>Item 3</span> <span>Item 4</span>
|
<span>Item 1</span> <span>Item 2</span> <span>Item 3</span> <span>Item 4</span>
|
||||||
@ -14,8 +12,6 @@ Fades out the siblings of a hovered item.
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
span {
|
span {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
@ -27,8 +23,6 @@ span {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `transition: opacity 0.2s` specifies that changes to opacity will be transitioned over 0.2 seconds.
|
1. `transition: opacity 0.2s` specifies that changes to opacity will be transitioned over 0.2 seconds.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Uses the native font of the operating system to get close to a native app feel.
|
Uses the native font of the operating system to get close to a native app feel.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="system-font-stack">This text uses the system font.</p>
|
<p class="system-font-stack">This text uses the system font.</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.system-font-stack {
|
.system-font-stack {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,
|
||||||
@ -20,8 +16,6 @@ Uses the native font of the operating system to get close to a native app feel.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
The browser looks for each successive font, preferring the first one if possible, and
|
The browser looks for each successive font, preferring the first one if possible, and
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual, interactivity,intermediate
|
|||||||
|
|
||||||
Creates a toggle switch with CSS only.
|
Creates a toggle switch with CSS only.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<input type="checkbox" id="toggle" class="offscreen" /> <label for="toggle" class="switch"></label>
|
<input type="checkbox" id="toggle" class="offscreen" /> <label for="toggle" class="switch"></label>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.switch {
|
.switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -50,8 +46,6 @@ input[type='checkbox']:checked + .switch {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
This effect is styling only the `<label>` element to look like a toggle switch, and hiding the actual `<input>` checkbox by positioning it offscreen. When clicking the label associated with the `<input>` element, it sets the `<input>` checkbox into the `:checked` state.
|
This effect is styling only the `<label>` element to look like a toggle switch, and hiding the actual `<input>` checkbox by positioning it offscreen. When clicking the label associated with the `<input>` element, it sets the `<input>` checkbox into the `:checked` state.
|
||||||
@ -69,7 +63,3 @@ This effect is styling only the `<label>` element to look like a toggle switch,
|
|||||||
<span class="snippet__support-note">⚠️ Requires prefixes for full support.</span>
|
<span class="snippet__support-note">⚠️ Requires prefixes for full support.</span>
|
||||||
|
|
||||||
- https://caniuse.com/#feat=transforms2d
|
- https://caniuse.com/#feat=transforms2d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- date: 2018-10-03 -->
|
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
Vertically and horizontally centers a child element within its parent element using `position: absolute` and `transform: translate()` (as an alternative to `flexbox` or `display: table`). Similar to `flexbox`, this method does not require you to know the height or width of your parent or child so it is ideal for responsive applications.
|
Vertically and horizontally centers a child element within its parent element using `position: absolute` and `transform: translate()` (as an alternative to `flexbox` or `display: table`). Similar to `flexbox`, this method does not require you to know the height or width of your parent or child so it is ideal for responsive applications.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="parent"><div class="child">Centered content</div></div>
|
<div class="parent"><div class="child">Centered content</div></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.parent {
|
.parent {
|
||||||
border: 1px solid #333;
|
border: 1px solid #333;
|
||||||
@ -30,8 +26,6 @@ Vertically and horizontally centers a child element within its parent element us
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `position: absolute` on the child element allows it to be positioned based on its containing block.
|
1. `position: absolute` on the child element allows it to be positioned based on its containing block.
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Creates a triangle shape with pure CSS.
|
Creates a triangle shape with pure CSS.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="triangle"></div>
|
<div class="triangle"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.triangle {
|
.triangle {
|
||||||
width: 0;
|
width: 0;
|
||||||
@ -23,8 +19,6 @@ Creates a triangle shape with pure CSS.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
[View this link for a detailed explanation.](https://stackoverflow.com/q/7073484)
|
[View this link for a detailed explanation.](https://stackoverflow.com/q/7073484)
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
If the text is longer than one line, it will be truncated for `n` lines and end with an gradient fade.
|
If the text is longer than one line, it will be truncated for `n` lines and end with an gradient fade.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="truncate-text-multiline">
|
<p class="truncate-text-multiline">
|
||||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
|
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
|
||||||
@ -14,8 +12,6 @@ If the text is longer than one line, it will be truncated for `n` lines and end
|
|||||||
</p>
|
</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.truncate-text-multiline {
|
.truncate-text-multiline {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -39,8 +35,6 @@ If the text is longer than one line, it will be truncated for `n` lines and end
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `overflow: hidden` prevents the text from overflowing its dimensions
|
1. `overflow: hidden` prevents the text from overflowing its dimensions
|
||||||
|
|||||||
@ -5,14 +5,10 @@ tags: layout,intermediate
|
|||||||
|
|
||||||
If the text is longer than one line, it will be truncated and end with an ellipsis `…`.
|
If the text is longer than one line, it will be truncated and end with an ellipsis `…`.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<p class="truncate-text">If I exceed one line's width, I will be truncated.</p>
|
<p class="truncate-text">If I exceed one line's width, I will be truncated.</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
.truncate-text {
|
.truncate-text {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -22,8 +18,6 @@ If the text is longer than one line, it will be truncated and end with an ellips
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. `overflow: hidden` prevents the text from overflowing its dimensions
|
1. `overflow: hidden` prevents the text from overflowing its dimensions
|
||||||
|
|||||||
@ -5,8 +5,6 @@ tags: visual,intermediate
|
|||||||
|
|
||||||
Creates a striped list with alternating background colors, which is useful for differentiating siblings that have content spread across a wide row.
|
Creates a striped list with alternating background colors, which is useful for differentiating siblings that have content spread across a wide row.
|
||||||
|
|
||||||
#### HTML
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<ul>
|
<ul>
|
||||||
<li>Item 01</li>
|
<li>Item 01</li>
|
||||||
@ -17,16 +15,12 @@ Creates a striped list with alternating background colors, which is useful for d
|
|||||||
</ul>
|
</ul>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CSS
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
li:nth-child(odd) {
|
li:nth-child(odd) {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Demo
|
|
||||||
|
|
||||||
#### Explanation
|
#### Explanation
|
||||||
|
|
||||||
1. Use the `:nth-child(odd)` or `:nth-child(even)` pseudo-class to apply a different background color to elements that match based on their position in a group of siblings.
|
1. Use the `:nth-child(odd)` or `:nth-child(even)` pseudo-class to apply a different background color to elements that match based on their position in a group of siblings.
|
||||||
@ -36,7 +30,3 @@ Note that you can use it to apply different styles to other HTML elements like d
|
|||||||
#### Browser support
|
#### Browser support
|
||||||
|
|
||||||
https://caniuse.com/#feat=css-sel3
|
https://caniuse.com/#feat=css-sel3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- date: 2018-10-31 -->
|
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
.back-to-top-button {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
background: white;
|
|
||||||
width: 4rem;
|
|
||||||
height: 4rem;
|
|
||||||
position: fixed;
|
|
||||||
right: 2rem;
|
|
||||||
bottom: 2rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
user-select: none;
|
|
||||||
box-shadow: 0 0.4rem 0.8rem -0.1rem rgba(0, 32, 128, 0.15);
|
|
||||||
transition: all 0.2s ease-out;
|
|
||||||
visibility: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
z-index: 1;
|
|
||||||
border: 1px solid rgba(0, 32, 128, 0.1);
|
|
||||||
outline: 0;
|
|
||||||
color: inherit;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
transform: scale(1.1);
|
|
||||||
box-shadow: 0 0.8rem 1.6rem -0.2rem rgba(0, 32, 128, 0.15);
|
|
||||||
color: #35a8ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
box-shadow: 0 0.8rem 1.6rem -0.2rem rgba(0, 32, 128, 0.15), 0 0 2px 2px #35a8ff;
|
|
||||||
outline-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-visible {
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feather {
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
html {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::after,
|
|
||||||
*::before {
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Roboto, Segoe UI, 'Helvetica Neue', Helvetica,
|
|
||||||
Arial, sans-serif;
|
|
||||||
background: #f2f3f8;
|
|
||||||
color: rgb(50, 75, 100);
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #157bda;
|
|
||||||
text-decoration: none;
|
|
||||||
word-wrap: break-word;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #0090ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid rgba(0, 32, 128, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,
|
|
||||||
ol {
|
|
||||||
padding-left: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 64rem;
|
|
||||||
padding: 0 2%;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main > .container {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 579px) {
|
|
||||||
.main > .container {
|
|
||||||
padding: 0 2%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
html {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.content-wrapper {
|
|
||||||
margin-left: 20%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1400px) {
|
|
||||||
.content-wrapper {
|
|
||||||
margin-left: 275px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #8385aa;
|
|
||||||
white-space: nowrap;
|
|
||||||
border: 1px solid #c8cbf2;
|
|
||||||
border-radius: 2px;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 2;
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
transition: all 0.1s ease-out;
|
|
||||||
outline: 0;
|
|
||||||
|
|
||||||
&.is-large {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
|
|
||||||
.feather {
|
|
||||||
top: -2px;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.feather {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button.btn {
|
|
||||||
user-select: none;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #8385aa;
|
|
||||||
border-color: #8385aa;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.focus-visible:focus {
|
|
||||||
box-shadow: 0 0 0 0.25rem transparentize(#8385aa, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
box-shadow: inset 0 0.1rem 0.1rem 0.1rem rgba(0, 0, 0, 0.2);
|
|
||||||
background: darken(#8385aa, 10);
|
|
||||||
border-color: darken(#8385aa, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
background: #7983ff;
|
|
||||||
border-color: #7983ff;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&.focus-visible:focus {
|
|
||||||
box-shadow: 0 0 0 0.25rem transparentize(#7983ff, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.codepen-btn {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,927 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Hamburgers
|
|
||||||
* @description Tasty CSS-animated hamburgers
|
|
||||||
* @author Jonathan Suh @jonsuh
|
|
||||||
* @site https://jonsuh.com/hamburgers
|
|
||||||
* @link https://github.com/jonsuh/hamburgers
|
|
||||||
*/
|
|
||||||
.hamburger {
|
|
||||||
padding: 1rem;
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
transition-property: opacity, filter;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
transition-timing-function: linear;
|
|
||||||
font: inherit;
|
|
||||||
color: inherit;
|
|
||||||
text-transform: none;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
margin: 0;
|
|
||||||
overflow: visible;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
.hamburger:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger-box {
|
|
||||||
width: 40px;
|
|
||||||
height: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger-inner {
|
|
||||||
display: block;
|
|
||||||
top: 50%;
|
|
||||||
}
|
|
||||||
.hamburger-inner,
|
|
||||||
.hamburger-inner::before,
|
|
||||||
.hamburger-inner::after {
|
|
||||||
width: 36px;
|
|
||||||
height: 2px;
|
|
||||||
background-color: #e3f5ff;
|
|
||||||
border-radius: 4px;
|
|
||||||
position: absolute;
|
|
||||||
transition-property: transform;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
transition-timing-function: ease;
|
|
||||||
}
|
|
||||||
.hamburger-inner::before,
|
|
||||||
.hamburger-inner::after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.hamburger-inner::before {
|
|
||||||
top: -10px;
|
|
||||||
}
|
|
||||||
.hamburger-inner::after {
|
|
||||||
bottom: -10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DX
|
|
||||||
*/
|
|
||||||
.hamburger--3dx .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dx .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dx .hamburger-inner::before,
|
|
||||||
.hamburger--3dx .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dx.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateY(180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dx.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dx.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DX Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--3dx-r .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dx-r .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dx-r .hamburger-inner::before,
|
|
||||||
.hamburger--3dx-r .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dx-r.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateY(-180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dx-r.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dx-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DY
|
|
||||||
*/
|
|
||||||
.hamburger--3dy .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dy .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dy .hamburger-inner::before,
|
|
||||||
.hamburger--3dy .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dy.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateX(-180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dy.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dy.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DY Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--3dy-r .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dy-r .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dy-r .hamburger-inner::before,
|
|
||||||
.hamburger--3dy-r .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dy-r.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateX(180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dy-r.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dy-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DXY
|
|
||||||
*/
|
|
||||||
.hamburger--3dxy .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dxy .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy .hamburger-inner::before,
|
|
||||||
.hamburger--3dxy .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dxy.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateX(180deg) rotateY(180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DXY Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--3dxy-r .hamburger-box {
|
|
||||||
perspective: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dxy-r .hamburger-inner {
|
|
||||||
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
|
|
||||||
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy-r .hamburger-inner::before,
|
|
||||||
.hamburger--3dxy-r .hamburger-inner::after {
|
|
||||||
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--3dxy-r.is-active .hamburger-inner {
|
|
||||||
background-color: transparent;
|
|
||||||
transform: rotateX(180deg) rotateY(180deg) rotateZ(-180deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy-r.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--3dxy-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow
|
|
||||||
*/
|
|
||||||
.hamburger--arrow.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrow.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow Right
|
|
||||||
*/
|
|
||||||
.hamburger--arrow-r.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(8px, 0, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrow-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(8px, 0, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow Alt
|
|
||||||
*/
|
|
||||||
.hamburger--arrowalt .hamburger-inner::before {
|
|
||||||
transition: top 0.1s 0.1s ease, transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt .hamburger-inner::after {
|
|
||||||
transition: bottom 0.1s 0.1s ease, transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: translate3d(-8px, -10px, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
transition: top 0.1s ease, transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: translate3d(-8px, 10px, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
transition: bottom 0.1s ease, transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow Alt Right
|
|
||||||
*/
|
|
||||||
.hamburger--arrowalt-r .hamburger-inner::before {
|
|
||||||
transition: top 0.1s 0.1s ease, transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt-r .hamburger-inner::after {
|
|
||||||
transition: bottom 0.1s 0.1s ease, transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: translate3d(8px, -10px, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
transition: top 0.1s ease, transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--arrowalt-r.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: translate3d(8px, 10px, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
transition: bottom 0.1s ease, transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow Turn
|
|
||||||
*/
|
|
||||||
.hamburger--arrowturn.is-active .hamburger-inner {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
.hamburger--arrowturn.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(8px, 0, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
.hamburger--arrowturn.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(8px, 0, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arrow Turn Right
|
|
||||||
*/
|
|
||||||
.hamburger--arrowturn-r.is-active .hamburger-inner {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
.hamburger--arrowturn-r.is-active .hamburger-inner::before {
|
|
||||||
transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
.hamburger--arrowturn-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Boring
|
|
||||||
*/
|
|
||||||
.hamburger--boring .hamburger-inner,
|
|
||||||
.hamburger--boring .hamburger-inner::before,
|
|
||||||
.hamburger--boring .hamburger-inner::after {
|
|
||||||
transition-property: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--boring.is-active .hamburger-inner {
|
|
||||||
transform: rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--boring.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--boring.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Collapse
|
|
||||||
*/
|
|
||||||
.hamburger--collapse .hamburger-inner {
|
|
||||||
top: auto;
|
|
||||||
bottom: 0;
|
|
||||||
transition-duration: 0.13s;
|
|
||||||
transition-delay: 0.13s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--collapse .hamburger-inner::after {
|
|
||||||
top: -20px;
|
|
||||||
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), opacity 0.1s linear;
|
|
||||||
}
|
|
||||||
.hamburger--collapse .hamburger-inner::before {
|
|
||||||
transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
|
|
||||||
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--collapse.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
transition-delay: 0.22s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--collapse.is-active .hamburger-inner::after {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333), opacity 0.1s 0.22s linear;
|
|
||||||
}
|
|
||||||
.hamburger--collapse.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
|
|
||||||
transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Collapse Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--collapse-r .hamburger-inner {
|
|
||||||
top: auto;
|
|
||||||
bottom: 0;
|
|
||||||
transition-duration: 0.13s;
|
|
||||||
transition-delay: 0.13s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--collapse-r .hamburger-inner::after {
|
|
||||||
top: -20px;
|
|
||||||
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), opacity 0.1s linear;
|
|
||||||
}
|
|
||||||
.hamburger--collapse-r .hamburger-inner::before {
|
|
||||||
transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
|
|
||||||
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--collapse-r.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(45deg);
|
|
||||||
transition-delay: 0.22s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--collapse-r.is-active .hamburger-inner::after {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333), opacity 0.1s 0.22s linear;
|
|
||||||
}
|
|
||||||
.hamburger--collapse-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
|
|
||||||
transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Elastic
|
|
||||||
*/
|
|
||||||
.hamburger--elastic .hamburger-inner {
|
|
||||||
top: 2px;
|
|
||||||
transition-duration: 0.275s;
|
|
||||||
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
}
|
|
||||||
.hamburger--elastic .hamburger-inner::before {
|
|
||||||
top: 10px;
|
|
||||||
transition: opacity 0.125s 0.275s ease;
|
|
||||||
}
|
|
||||||
.hamburger--elastic .hamburger-inner::after {
|
|
||||||
top: 20px;
|
|
||||||
transition: transform 0.275s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--elastic.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(135deg);
|
|
||||||
transition-delay: 0.075s;
|
|
||||||
}
|
|
||||||
.hamburger--elastic.is-active .hamburger-inner::before {
|
|
||||||
transition-delay: 0s;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--elastic.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -20px, 0) rotate(-270deg);
|
|
||||||
transition-delay: 0.075s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Elastic Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--elastic-r .hamburger-inner {
|
|
||||||
top: 2px;
|
|
||||||
transition-duration: 0.275s;
|
|
||||||
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
}
|
|
||||||
.hamburger--elastic-r .hamburger-inner::before {
|
|
||||||
top: 10px;
|
|
||||||
transition: opacity 0.125s 0.275s ease;
|
|
||||||
}
|
|
||||||
.hamburger--elastic-r .hamburger-inner::after {
|
|
||||||
top: 20px;
|
|
||||||
transition: transform 0.275s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--elastic-r.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(-135deg);
|
|
||||||
transition-delay: 0.075s;
|
|
||||||
}
|
|
||||||
.hamburger--elastic-r.is-active .hamburger-inner::before {
|
|
||||||
transition-delay: 0s;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--elastic-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -20px, 0) rotate(270deg);
|
|
||||||
transition-delay: 0.075s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Emphatic
|
|
||||||
*/
|
|
||||||
.hamburger--emphatic {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic .hamburger-inner {
|
|
||||||
transition: background-color 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic .hamburger-inner::before {
|
|
||||||
left: 0;
|
|
||||||
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335), top 0.05s 0.125s linear,
|
|
||||||
left 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic .hamburger-inner::after {
|
|
||||||
top: 10px;
|
|
||||||
right: 0;
|
|
||||||
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335), top 0.05s 0.125s linear,
|
|
||||||
right 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic.is-active .hamburger-inner {
|
|
||||||
transition-delay: 0s;
|
|
||||||
transition-timing-function: ease-out;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic.is-active .hamburger-inner::before {
|
|
||||||
left: -80px;
|
|
||||||
top: -80px;
|
|
||||||
transform: translate3d(80px, 80px, 0) rotate(45deg);
|
|
||||||
transition: left 0.125s ease-out, top 0.05s 0.125s linear,
|
|
||||||
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
||||||
}
|
|
||||||
.hamburger--emphatic.is-active .hamburger-inner::after {
|
|
||||||
right: -80px;
|
|
||||||
top: -80px;
|
|
||||||
transform: translate3d(-80px, 80px, 0) rotate(-45deg);
|
|
||||||
transition: right 0.125s ease-out, top 0.05s 0.125s linear,
|
|
||||||
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Emphatic Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--emphatic-r {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r .hamburger-inner {
|
|
||||||
transition: background-color 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r .hamburger-inner::before {
|
|
||||||
left: 0;
|
|
||||||
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335), top 0.05s 0.125s linear,
|
|
||||||
left 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r .hamburger-inner::after {
|
|
||||||
top: 10px;
|
|
||||||
right: 0;
|
|
||||||
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335), top 0.05s 0.125s linear,
|
|
||||||
right 0.125s 0.175s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r.is-active .hamburger-inner {
|
|
||||||
transition-delay: 0s;
|
|
||||||
transition-timing-function: ease-out;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r.is-active .hamburger-inner::before {
|
|
||||||
left: -80px;
|
|
||||||
top: 80px;
|
|
||||||
transform: translate3d(80px, -80px, 0) rotate(-45deg);
|
|
||||||
transition: left 0.125s ease-out, top 0.05s 0.125s linear,
|
|
||||||
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
||||||
}
|
|
||||||
.hamburger--emphatic-r.is-active .hamburger-inner::after {
|
|
||||||
right: -80px;
|
|
||||||
top: 80px;
|
|
||||||
transform: translate3d(-80px, -80px, 0) rotate(45deg);
|
|
||||||
transition: right 0.125s ease-out, top 0.05s 0.125s linear,
|
|
||||||
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Minus
|
|
||||||
*/
|
|
||||||
.hamburger--minus .hamburger-inner::before,
|
|
||||||
.hamburger--minus .hamburger-inner::after {
|
|
||||||
transition: bottom 0.08s 0s ease-out, top 0.08s 0s ease-out, opacity 0s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--minus.is-active .hamburger-inner::before,
|
|
||||||
.hamburger--minus.is-active .hamburger-inner::after {
|
|
||||||
opacity: 0;
|
|
||||||
transition: bottom 0.08s ease-out, top 0.08s ease-out, opacity 0s 0.08s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--minus.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--minus.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Slider
|
|
||||||
*/
|
|
||||||
.hamburger--slider .hamburger-inner {
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
.hamburger--slider .hamburger-inner::before {
|
|
||||||
top: 10px;
|
|
||||||
transition-property: transform, opacity;
|
|
||||||
transition-timing-function: ease;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
}
|
|
||||||
.hamburger--slider .hamburger-inner::after {
|
|
||||||
top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--slider.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--slider.is-active .hamburger-inner::before {
|
|
||||||
transform: rotate(-45deg) translate3d(-5.71429px, -6px, 0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--slider.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -20px, 0) rotate(-90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Slider Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--slider-r .hamburger-inner {
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
.hamburger--slider-r .hamburger-inner::before {
|
|
||||||
top: 10px;
|
|
||||||
transition-property: transform, opacity;
|
|
||||||
transition-timing-function: ease;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
}
|
|
||||||
.hamburger--slider-r .hamburger-inner::after {
|
|
||||||
top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--slider-r.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
.hamburger--slider-r.is-active .hamburger-inner::before {
|
|
||||||
transform: rotate(45deg) translate3d(5.71429px, -6px, 0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--slider-r.is-active .hamburger-inner::after {
|
|
||||||
transform: translate3d(0, -20px, 0) rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spin
|
|
||||||
*/
|
|
||||||
.hamburger--spin .hamburger-inner {
|
|
||||||
transition-duration: 0.22s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--spin .hamburger-inner::before {
|
|
||||||
transition: top 0.1s 0.25s ease-in, opacity 0.1s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--spin .hamburger-inner::after {
|
|
||||||
transition: bottom 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--spin.is-active .hamburger-inner {
|
|
||||||
transform: rotate(225deg);
|
|
||||||
transition-delay: 0.12s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--spin.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.1s ease-out, opacity 0.1s 0.12s ease-out;
|
|
||||||
}
|
|
||||||
.hamburger--spin.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
transition: bottom 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spin Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--spin-r .hamburger-inner {
|
|
||||||
transition-duration: 0.22s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--spin-r .hamburger-inner::before {
|
|
||||||
transition: top 0.1s 0.25s ease-in, opacity 0.1s ease-in;
|
|
||||||
}
|
|
||||||
.hamburger--spin-r .hamburger-inner::after {
|
|
||||||
transition: bottom 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--spin-r.is-active .hamburger-inner {
|
|
||||||
transform: rotate(-225deg);
|
|
||||||
transition-delay: 0.12s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--spin-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.1s ease-out, opacity 0.1s 0.12s ease-out;
|
|
||||||
}
|
|
||||||
.hamburger--spin-r.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
transition: bottom 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spring
|
|
||||||
*/
|
|
||||||
.hamburger--spring .hamburger-inner {
|
|
||||||
top: 2px;
|
|
||||||
transition: background-color 0s 0.13s linear;
|
|
||||||
}
|
|
||||||
.hamburger--spring .hamburger-inner::before {
|
|
||||||
top: 10px;
|
|
||||||
transition: top 0.1s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
|
|
||||||
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--spring .hamburger-inner::after {
|
|
||||||
top: 20px;
|
|
||||||
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
|
|
||||||
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--spring.is-active .hamburger-inner {
|
|
||||||
transition-delay: 0.22s;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.hamburger--spring.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transition: top 0.1s 0.15s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
|
|
||||||
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
.hamburger--spring.is-active .hamburger-inner::after {
|
|
||||||
top: 0;
|
|
||||||
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
|
|
||||||
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
transform: translate3d(0, 10px, 0) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spring Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--spring-r .hamburger-inner {
|
|
||||||
top: auto;
|
|
||||||
bottom: 0;
|
|
||||||
transition-duration: 0.13s;
|
|
||||||
transition-delay: 0s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--spring-r .hamburger-inner::after {
|
|
||||||
top: -20px;
|
|
||||||
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), opacity 0s linear;
|
|
||||||
}
|
|
||||||
.hamburger--spring-r .hamburger-inner::before {
|
|
||||||
transition: top 0.1s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
|
|
||||||
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--spring-r.is-active .hamburger-inner {
|
|
||||||
transform: translate3d(0, -10px, 0) rotate(-45deg);
|
|
||||||
transition-delay: 0.22s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--spring-r.is-active .hamburger-inner::after {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333), opacity 0s 0.22s linear;
|
|
||||||
}
|
|
||||||
.hamburger--spring-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
transition: top 0.1s 0.15s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
|
|
||||||
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stand
|
|
||||||
*/
|
|
||||||
.hamburger--stand .hamburger-inner {
|
|
||||||
transition: transform 0.075s 0.15s cubic-bezier(0.55, 0.055, 0.675, 0.19),
|
|
||||||
background-color 0s 0.075s linear;
|
|
||||||
}
|
|
||||||
.hamburger--stand .hamburger-inner::before {
|
|
||||||
transition: top 0.075s 0.075s ease-in, transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--stand .hamburger-inner::after {
|
|
||||||
transition: bottom 0.075s 0.075s ease-in,
|
|
||||||
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--stand.is-active .hamburger-inner {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
background-color: transparent;
|
|
||||||
transition: transform 0.075s 0s cubic-bezier(0.215, 0.61, 0.355, 1),
|
|
||||||
background-color 0s 0.15s linear;
|
|
||||||
}
|
|
||||||
.hamburger--stand.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
transition: top 0.075s 0.1s ease-out, transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--stand.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
transition: bottom 0.075s 0.1s ease-out,
|
|
||||||
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stand Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--stand-r .hamburger-inner {
|
|
||||||
transition: transform 0.075s 0.15s cubic-bezier(0.55, 0.055, 0.675, 0.19),
|
|
||||||
background-color 0s 0.075s linear;
|
|
||||||
}
|
|
||||||
.hamburger--stand-r .hamburger-inner::before {
|
|
||||||
transition: top 0.075s 0.075s ease-in, transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--stand-r .hamburger-inner::after {
|
|
||||||
transition: bottom 0.075s 0.075s ease-in,
|
|
||||||
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--stand-r.is-active .hamburger-inner {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
background-color: transparent;
|
|
||||||
transition: transform 0.075s 0s cubic-bezier(0.215, 0.61, 0.355, 1),
|
|
||||||
background-color 0s 0.15s linear;
|
|
||||||
}
|
|
||||||
.hamburger--stand-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
transition: top 0.075s 0.1s ease-out, transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--stand-r.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
transition: bottom 0.075s 0.1s ease-out,
|
|
||||||
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Squeeze
|
|
||||||
*/
|
|
||||||
.hamburger--squeeze .hamburger-inner {
|
|
||||||
transition-duration: 0.075s;
|
|
||||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
.hamburger--squeeze .hamburger-inner::before {
|
|
||||||
transition: top 0.075s 0.12s ease, opacity 0.075s ease;
|
|
||||||
}
|
|
||||||
.hamburger--squeeze .hamburger-inner::after {
|
|
||||||
transition: bottom 0.075s 0.12s ease, transform 0.075s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--squeeze.is-active .hamburger-inner {
|
|
||||||
transform: rotate(45deg);
|
|
||||||
transition-delay: 0.12s;
|
|
||||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
.hamburger--squeeze.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: top 0.075s ease, opacity 0.075s 0.12s ease;
|
|
||||||
}
|
|
||||||
.hamburger--squeeze.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
transition: bottom 0.075s ease, transform 0.075s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Vortex
|
|
||||||
*/
|
|
||||||
.hamburger--vortex .hamburger-inner {
|
|
||||||
transition-duration: 0.2s;
|
|
||||||
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
|
|
||||||
}
|
|
||||||
.hamburger--vortex .hamburger-inner::before,
|
|
||||||
.hamburger--vortex .hamburger-inner::after {
|
|
||||||
transition-duration: 0s;
|
|
||||||
transition-delay: 0.1s;
|
|
||||||
transition-timing-function: linear;
|
|
||||||
}
|
|
||||||
.hamburger--vortex .hamburger-inner::before {
|
|
||||||
transition-property: top, opacity;
|
|
||||||
}
|
|
||||||
.hamburger--vortex .hamburger-inner::after {
|
|
||||||
transition-property: bottom, transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--vortex.is-active .hamburger-inner {
|
|
||||||
transform: rotate(765deg);
|
|
||||||
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
|
|
||||||
}
|
|
||||||
.hamburger--vortex.is-active .hamburger-inner::before,
|
|
||||||
.hamburger--vortex.is-active .hamburger-inner::after {
|
|
||||||
transition-delay: 0s;
|
|
||||||
}
|
|
||||||
.hamburger--vortex.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--vortex.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Vortex Reverse
|
|
||||||
*/
|
|
||||||
.hamburger--vortex-r .hamburger-inner {
|
|
||||||
transition-duration: 0.2s;
|
|
||||||
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r .hamburger-inner::before,
|
|
||||||
.hamburger--vortex-r .hamburger-inner::after {
|
|
||||||
transition-duration: 0s;
|
|
||||||
transition-delay: 0.1s;
|
|
||||||
transition-timing-function: linear;
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r .hamburger-inner::before {
|
|
||||||
transition-property: top, opacity;
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r .hamburger-inner::after {
|
|
||||||
transition-property: bottom, transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger--vortex-r.is-active .hamburger-inner {
|
|
||||||
transform: rotate(-765deg);
|
|
||||||
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r.is-active .hamburger-inner::before,
|
|
||||||
.hamburger--vortex-r.is-active .hamburger-inner::after {
|
|
||||||
transition-delay: 0s;
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r.is-active .hamburger-inner::before {
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hamburger--vortex-r.is-active .hamburger-inner::after {
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
.header {
|
|
||||||
position: relative;
|
|
||||||
padding: 5rem 1rem 4rem;
|
|
||||||
background: #5b67ff;
|
|
||||||
background: linear-gradient(25deg, #95e2ff, #5f79ff, #8ed5ff);
|
|
||||||
color: white;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
width: 150%;
|
|
||||||
height: 150%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
opacity: 0.1;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 12'%3E%3Cpath d='m12 0l12 12h-24z' fill='%23f2f3f8'/%3E%3C/svg%3E");
|
|
||||||
background-size: 24px 24px;
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
height: 24px;
|
|
||||||
bottom: -7px;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
position: relative;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__logo {
|
|
||||||
height: 146px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__heading {
|
|
||||||
font-weight: 300;
|
|
||||||
font-size: 3rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__description {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto 2rem;
|
|
||||||
font-weight: 300;
|
|
||||||
letter-spacing: 0.4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__css {
|
|
||||||
font-size: 4rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__github-button-wrapper {
|
|
||||||
height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__github-button {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__leaves {
|
|
||||||
position: absolute;
|
|
||||||
width: 250px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#header__blob {
|
|
||||||
position: absolute;
|
|
||||||
width: 240px;
|
|
||||||
left: -25px;
|
|
||||||
top: 50px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header__leaves1 {
|
|
||||||
right: -100px;
|
|
||||||
top: -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header__leaves2 {
|
|
||||||
left: -250px;
|
|
||||||
bottom: -100px;
|
|
||||||
transform: rotate(235deg);
|
|
||||||
z-index: 2;
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1150px) {
|
|
||||||
#header__leaves2 {
|
|
||||||
left: -100px;
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#header__blob {
|
|
||||||
left: 50px;
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 579px) {
|
|
||||||
.header {
|
|
||||||
padding: 6rem 0 5rem;
|
|
||||||
|
|
||||||
&__heading {
|
|
||||||
font-size: 3.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.header {
|
|
||||||
padding: 2.5rem 0 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
.sidebar {
|
|
||||||
background: #273149;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 2;
|
|
||||||
width: 100%;
|
|
||||||
height: 44px;
|
|
||||||
box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 128, 0.2);
|
|
||||||
|
|
||||||
&__menu {
|
|
||||||
position: absolute;
|
|
||||||
font-weight: bold;
|
|
||||||
border: none;
|
|
||||||
text-align: left;
|
|
||||||
text-transform: uppercase;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__menu-icon {
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__links {
|
|
||||||
background: #273149;
|
|
||||||
overflow-y: auto;
|
|
||||||
transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
|
||||||
transform-origin: 0% 0%;
|
|
||||||
transform: rotateX(-90deg);
|
|
||||||
visibility: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
overflow-y: auto;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
max-height: 378px;
|
|
||||||
margin-top: 44px;
|
|
||||||
box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 128, 0.2);
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
transform: rotateX(0);
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__link {
|
|
||||||
display: block;
|
|
||||||
color: #e3f5ff;
|
|
||||||
padding: 0.75rem;
|
|
||||||
padding-right: 1.5rem;
|
|
||||||
margin-right: -0.75rem;
|
|
||||||
transition: all 0.1s ease-out;
|
|
||||||
border-left: 2px solid #576a85;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #88f4ff;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-color: pink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__section {
|
|
||||||
padding: 0 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__section-heading {
|
|
||||||
text-transform: capitalize;
|
|
||||||
color: #e3f5ff;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__new {
|
|
||||||
width: 1.25rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.sidebar {
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 20%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(-30deg, #273149, #1c273f);
|
|
||||||
box-shadow: 0.4rem 0.4rem 0.8rem rgba(0, 32, 64, 0.1);
|
|
||||||
overflow-y: auto;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
@media (min-width: 1400px) {
|
|
||||||
width: 275px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__links {
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
transform: rotateX(0);
|
|
||||||
margin-top: 0;
|
|
||||||
max-height: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__menu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.macOS) {
|
|
||||||
.sidebar {
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 10px;
|
|
||||||
background-color: #505b76;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #505b76;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
.snippet {
|
|
||||||
position: relative;
|
|
||||||
background: white;
|
|
||||||
padding: 2rem 5%;
|
|
||||||
box-shadow: 0 0.4rem 0.8rem -0.1rem rgba(0, 32, 128, 0.1), 0 0 0 1px #f0f2f7;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 2rem;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
border-bottom: 1px solid rgba(0, 32, 128, 0.1);
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
margin-top: 0;
|
|
||||||
line-height: 1.3;
|
|
||||||
|
|
||||||
span:not(.snippet__tag) {
|
|
||||||
margin-right: 0.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code:not([class*='lang']) {
|
|
||||||
background: #fcfaff;
|
|
||||||
border: 1px solid #e2ddff;
|
|
||||||
color: #4b00da;
|
|
||||||
border-radius: 0.15rem;
|
|
||||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 0.2rem 0.4rem;
|
|
||||||
margin: 0 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol > li {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
> p {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 1rem 0 0.5rem;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
line-height: 2;
|
|
||||||
|
|
||||||
&[data-type] {
|
|
||||||
background: #333;
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
border: 1px solid #c6d6ea;
|
|
||||||
border-bottom-color: darken(#c6d6ea, 5);
|
|
||||||
background: white;
|
|
||||||
box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 64, 0.15);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-type='HTML'] {
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
background-image: linear-gradient(135deg, #ff4c9f, #ff7b74);
|
|
||||||
}
|
|
||||||
&[data-type='CSS'] {
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
background-image: linear-gradient(135deg, #7983ff, #5f9de9);
|
|
||||||
}
|
|
||||||
&[data-type='JavaScript'] {
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
background-image: linear-gradient(135deg, #ffb000, #f58818);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__browser-support {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 200;
|
|
||||||
line-height: 1;
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__subheading.is-html {
|
|
||||||
color: #e22f70;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__subheading.is-css {
|
|
||||||
color: #0a91d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__subheading.is-explanation {
|
|
||||||
color: #4b00da;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__support-note {
|
|
||||||
color: #9fa5b5;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__requires-javascript {
|
|
||||||
position: absolute;
|
|
||||||
background: red;
|
|
||||||
background: linear-gradient(145deg, #ff003b, #ff4b39);
|
|
||||||
color: white;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
transform: rotate(20deg);
|
|
||||||
font-weight: bold;
|
|
||||||
top: 1rem;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__tag {
|
|
||||||
}
|
|
||||||
|
|
||||||
&__new {
|
|
||||||
position: absolute;
|
|
||||||
top: -1rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
width: 3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.snippet-demo {
|
|
||||||
background: #f5f6f9;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
padding: 0.75rem 1.25rem;
|
|
||||||
|
|
||||||
&.is-distinct {
|
|
||||||
background: linear-gradient(135deg, #ff4c9f, #ff7b74);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.snippet {
|
|
||||||
&__requires-javascript {
|
|
||||||
right: -0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
.tags {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding: 0 1rem;
|
|
||||||
|
|
||||||
&__tag {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #8385aa;
|
|
||||||
white-space: nowrap;
|
|
||||||
border: 1px solid #c8cbf2;
|
|
||||||
border-radius: 2px;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 2;
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
margin: 0 0.1rem;
|
|
||||||
transition: all 0.1s ease-out;
|
|
||||||
outline: 0;
|
|
||||||
|
|
||||||
&.is-large {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
|
|
||||||
.feather {
|
|
||||||
top: -2px;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.feather {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button.tags__tag {
|
|
||||||
user-select: none;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #8385aa;
|
|
||||||
border-color: #8385aa;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.focus-visible:focus {
|
|
||||||
box-shadow: 0 0 0 0.25rem transparentize(#8385aa, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
box-shadow: inset 0 0.1rem 0.1rem 0.1rem rgba(0, 0, 0, 0.2);
|
|
||||||
background: darken(#8385aa, 10);
|
|
||||||
border-color: darken(#8385aa, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
background: #7983ff;
|
|
||||||
border-color: #7983ff;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&.focus-visible:focus {
|
|
||||||
box-shadow: 0 0 0 0.25rem transparentize(#7983ff, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 579px) {
|
|
||||||
}
|
|
||||||
@ -1,147 +0,0 @@
|
|||||||
code[class*='language-'],
|
|
||||||
pre[class*='language-'] {
|
|
||||||
color: rgb(215, 236, 255);
|
|
||||||
background: none;
|
|
||||||
font-family: 'Operator Mono', 'Roboto Mono', Menlo, Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono',
|
|
||||||
monospace;
|
|
||||||
text-align: left;
|
|
||||||
white-space: pre;
|
|
||||||
word-spacing: normal;
|
|
||||||
word-break: normal;
|
|
||||||
word-wrap: normal;
|
|
||||||
line-height: 2;
|
|
||||||
font-size: 1rem;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
-moz-tab-size: 4;
|
|
||||||
-o-tab-size: 4;
|
|
||||||
tab-size: 4;
|
|
||||||
|
|
||||||
-webkit-hyphens: none;
|
|
||||||
-moz-hyphens: none;
|
|
||||||
-ms-hyphens: none;
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre[class*='language-']::-moz-selection,
|
|
||||||
pre[class*='language-'] ::-moz-selection,
|
|
||||||
code[class*='language-']::-moz-selection,
|
|
||||||
code[class*='language-'] ::-moz-selection {
|
|
||||||
text-shadow: none;
|
|
||||||
background: #b3d4fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre[class*='language-']::selection,
|
|
||||||
pre[class*='language-'] ::selection,
|
|
||||||
code[class*='language-']::selection,
|
|
||||||
code[class*='language-'] ::selection {
|
|
||||||
text-shadow: none;
|
|
||||||
background: #b3d4fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
code[class*='language-'],
|
|
||||||
pre[class*='language-'] {
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Code blocks */
|
|
||||||
pre[class*='language-'] {
|
|
||||||
overflow: auto;
|
|
||||||
padding: 0.75rem 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre.is-option {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:not(pre) > code[class*='language-'],
|
|
||||||
pre[class*='language-'] {
|
|
||||||
background: linear-gradient(-30deg, #273149, #1c273f);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Inline code */
|
|
||||||
:not(pre) > code[class*='language-'] {
|
|
||||||
padding: 0.1em;
|
|
||||||
border-radius: 0.3em;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.comment,
|
|
||||||
.token.prolog,
|
|
||||||
.token.doctype,
|
|
||||||
.token.cdata {
|
|
||||||
color: #8ca2d3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.selector,
|
|
||||||
.token.attr-name {
|
|
||||||
color: #c7f683;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.punctuation {
|
|
||||||
color: #5ac8e3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.namespace {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.tag {
|
|
||||||
color: #2cefd8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.property,
|
|
||||||
.token.boolean,
|
|
||||||
.token.number,
|
|
||||||
.token.constant,
|
|
||||||
.token.symbol,
|
|
||||||
.token.deleted {
|
|
||||||
color: #85b4ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.string,
|
|
||||||
.language-css .token.string,
|
|
||||||
.token.url,
|
|
||||||
.token.attr-value,
|
|
||||||
.token.char,
|
|
||||||
.token.builtin,
|
|
||||||
.token.inserted {
|
|
||||||
color: #ffd694;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.operator,
|
|
||||||
.token.entity,
|
|
||||||
.style .token.string {
|
|
||||||
color: #ff9bbe;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.important,
|
|
||||||
.token.atrule,
|
|
||||||
.token.keyword {
|
|
||||||
color: #b7adff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.function {
|
|
||||||
color: #25d0e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.regex,
|
|
||||||
.token.variable {
|
|
||||||
color: #00a8d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.token.italic {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.entity {
|
|
||||||
cursor: help;
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
@import './components/base.scss';
|
|
||||||
@import './components/hamburger.scss';
|
|
||||||
@import './components/sidebar.scss';
|
|
||||||
@import './components/header.scss';
|
|
||||||
@import './components/snippet.scss';
|
|
||||||
@import './components/back-to-top-button.scss';
|
|
||||||
@import './components/tags.scss';
|
|
||||||
@import './components/buttons.scss';
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<button class="back-to-top-button" aria-label="back to top"><i data-feather="arrow-up"></i></button>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<footer class="footer"></footer>
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<header class="header">
|
|
||||||
<div class="container">
|
|
||||||
<img class="header__leaves" draggable="false" id="header__leaves1" src="./src/img/leaves.svg" alt>
|
|
||||||
<img class="header__leaves" draggable="false" id="header__leaves2" src="./src/img/leaves.svg" alt>
|
|
||||||
<img id="header__blob" draggable="false" src="./src/img/blob.png" alt>
|
|
||||||
<div class="header__content">
|
|
||||||
<img class="header__logo" draggable="false" src="./src/img/logo.png">
|
|
||||||
<h1 class="header__heading">30 Seconds of <strong class="header__css">CSS</strong></h1>
|
|
||||||
<p class="header__description">
|
|
||||||
A curated collection of useful CSS snippets you can understand in 30 seconds or less.
|
|
||||||
</p>
|
|
||||||
<div class="header__github-button-wrapper">
|
|
||||||
<a class="github-button header__github-button" href="https://github.com/30-seconds/30-seconds-of-css" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star 30-seconds/30-seconds-of-css on GitHub">Star</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
<main class="main" id="main">
|
|
||||||
<div class="container">
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<nav class="sidebar" aria-label="Table of Contents">
|
|
||||||
<button class="hamburger hamburger--spin sidebar__menu" type="button" aria-label="Menu" aria-expanded="false">
|
|
||||||
<span class="hamburger-box">
|
|
||||||
<span class="hamburger-inner"></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<div class="sidebar__links">
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<nav class="tags" aria-label="Filter by tags"></nav>
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
||||||
<title>30 Seconds of CSS</title>
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png" />
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="A curated collection of useful CSS snippets you can understand in 30 seconds or less. From foundational elements such as clearfix to gradient text color and gradient cursor tracking to CSS easing and far beyond."
|
|
||||||
/>
|
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
|
||||||
<meta property="twitter:url" content="https://30-seconds.github.io/30-seconds-of-css/" />
|
|
||||||
<meta property="twitter:title" content="30 Seconds of CSS - Useful CSS snippets" />
|
|
||||||
<meta
|
|
||||||
property="twitter:description"
|
|
||||||
content="A curated collection of useful CSS snippets you can understand in 30 seconds or less. "
|
|
||||||
/>
|
|
||||||
<meta property="twitter:image" content="./src/img/opengraph.png" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:url" content="https://30-seconds.github.io/30-seconds-of-css/" />
|
|
||||||
<meta property="og:title" content="30 Seconds of CSS - Useful CSS snippets" />
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="A curated collection of useful CSS snippets you can understand in 30 seconds or less."
|
|
||||||
/>
|
|
||||||
<meta property="og:image" content="./src/img/opengraph.png" />
|
|
||||||
<script src="./src/js/index.js" defer=""></script>
|
|
||||||
<script async="" defer="" src="https://buttons.github.io/buttons.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="content-wrapper"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
BIN
src/img/blob.png
|
Before Width: | Height: | Size: 255 KiB |
|
Before Width: | Height: | Size: 14 KiB |
BIN
src/img/logo.png
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 400 KiB |
@ -1,14 +0,0 @@
|
|||||||
import jump from 'jump.js'
|
|
||||||
import { select, scrollY, easeOutQuint } from '../deps/utils'
|
|
||||||
|
|
||||||
const backToTopButton = select('.back-to-top-button')
|
|
||||||
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
backToTopButton.classList[scrollY() > 500 ? 'add' : 'remove']('is-visible')
|
|
||||||
})
|
|
||||||
backToTopButton.onclick = () => {
|
|
||||||
jump('.header', {
|
|
||||||
duration: 750,
|
|
||||||
easing: easeOutQuint
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import { selectAll } from '../deps/utils'
|
|
||||||
|
|
||||||
const snippets = selectAll('.snippet')
|
|
||||||
snippets.forEach(snippet => {
|
|
||||||
var codepenForm = document.createElement('form')
|
|
||||||
codepenForm.action = 'https://codepen.io/pen/define'
|
|
||||||
codepenForm.method = 'POST'
|
|
||||||
codepenForm.target = '_blank'
|
|
||||||
var codepenInput = document.createElement('input')
|
|
||||||
codepenInput.type = 'hidden'
|
|
||||||
codepenInput.name = 'data'
|
|
||||||
var codepenButton = document.createElement('button')
|
|
||||||
codepenButton.classList = 'btn is-large codepen-btn'
|
|
||||||
codepenButton.innerHTML = '<i data-feather="edit-2"></i>Edit on Codepen'
|
|
||||||
var css = snippet.querySelector('pre code.lang-css')
|
|
||||||
var html = snippet.querySelector('pre code.lang-html')
|
|
||||||
var js = snippet.querySelector('pre code.lang-js')
|
|
||||||
var data = {
|
|
||||||
css: css.textContent,
|
|
||||||
title: snippet.querySelector('h3 > span').textContent,
|
|
||||||
html: html ? html.textContent : '',
|
|
||||||
js: js ? js.textContent : ''
|
|
||||||
}
|
|
||||||
codepenInput.value = JSON.stringify(data)
|
|
||||||
codepenForm.appendChild(codepenInput)
|
|
||||||
codepenForm.appendChild(codepenButton)
|
|
||||||
snippet.insertBefore(codepenForm, snippet.querySelector('.snippet-demo').nextSibling)
|
|
||||||
})
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
import jump from 'jump.js'
|
|
||||||
import { select, selectAll, easeOutQuint } from '../deps/utils'
|
|
||||||
|
|
||||||
const menu = select('.hamburger')
|
|
||||||
const links = select('.sidebar__links')
|
|
||||||
const sections = selectAll('.sidebar__section')
|
|
||||||
const ACTIVE_CLASS = 'is-active'
|
|
||||||
|
|
||||||
const toggle = () => {
|
|
||||||
if (window.innerWidth <= 991) {
|
|
||||||
const els = [menu, links]
|
|
||||||
els.forEach(el => el.classList.toggle(ACTIVE_CLASS))
|
|
||||||
menu.setAttribute('aria-expanded', menu.classList.contains(ACTIVE_CLASS) ? 'true' : 'false')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.addEventListener('click', toggle)
|
|
||||||
|
|
||||||
links.addEventListener('click', e => {
|
|
||||||
const link = e.target.closest('.sidebar__link')
|
|
||||||
if (link) {
|
|
||||||
setTimeout(toggle, 50)
|
|
||||||
jump(link.getAttribute('href'), {
|
|
||||||
duration: 500,
|
|
||||||
easing: easeOutQuint,
|
|
||||||
offset: window.innerWidth <= 991 ? -64 : -32
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
document.addEventListener('click', e => {
|
|
||||||
if (
|
|
||||||
!e.target.closest('.sidebar__links') &&
|
|
||||||
!e.target.closest('.hamburger') &&
|
|
||||||
links.classList.contains(ACTIVE_CLASS)
|
|
||||||
) {
|
|
||||||
toggle()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
EventHub.on('Tag.click', data => {
|
|
||||||
data.type_new = data.type.map(el => el.dataset.type)
|
|
||||||
sections.forEach(section => {
|
|
||||||
section.style.display = 'block'
|
|
||||||
//console.log(data.type_new.includes('all'))
|
|
||||||
if (!data.type_new.includes(section.dataset.type) && !data.type_new.includes('all')) {
|
|
||||||
section.style.display = 'none'
|
|
||||||
} else {
|
|
||||||
section.style.display = ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
export default { toggle }
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
import { selectAll } from '../deps/utils'
|
|
||||||
|
|
||||||
const snippets = selectAll('.snippet')
|
|
||||||
EventHub.on('Tag.click', data => {
|
|
||||||
data.type_new = data.type.map(el => el.dataset.type)
|
|
||||||
snippets.forEach(snippet => {
|
|
||||||
snippet.style.display = 'block'
|
|
||||||
if (data.type_new.includes('all')) return
|
|
||||||
const tags = selectAll('.tags__tag', snippet)
|
|
||||||
if (!tags.some(el => data.type_new.includes(el.dataset.type))) {
|
|
||||||
snippet.style.display = 'none'
|
|
||||||
} else {
|
|
||||||
snippet.style.display = ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
import { select, selectAll, on } from '../deps/utils'
|
|
||||||
|
|
||||||
const tagButtons = selectAll('button.tags__tag')
|
|
||||||
var isShiftSelected = false
|
|
||||||
const onClick = function() {
|
|
||||||
if (isShiftSelected && this.dataset.type === 'all') {
|
|
||||||
tagButtons.forEach(button => button.classList.remove('is-active'))
|
|
||||||
this.classList.add('is-active')
|
|
||||||
} else if (isShiftSelected) {
|
|
||||||
select('button[data-type=all]').classList.remove('is-active')
|
|
||||||
if (
|
|
||||||
this.classList.contains('is-active') &&
|
|
||||||
selectAll('button.tags__tag.is-active').length > 1
|
|
||||||
) {
|
|
||||||
this.classList.remove('is-active')
|
|
||||||
} else if (this.classList.contains('is-active')) {
|
|
||||||
this.classList.remove('is-active')
|
|
||||||
select('button[data-type=all]').classList.add('is-active')
|
|
||||||
} else {
|
|
||||||
this.classList.add('is-active')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tagButtons.forEach(button => button.classList.remove('is-active'))
|
|
||||||
this.classList.add('is-active')
|
|
||||||
}
|
|
||||||
EventHub.emit('Tag.click', {
|
|
||||||
type: [...selectAll('button.tags__tag.is-active')]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onkeydown = e => {
|
|
||||||
if (e.shiftKey) {
|
|
||||||
isShiftSelected = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onkeyup = e => {
|
|
||||||
if (e.key == 'Shift') {
|
|
||||||
isShiftSelected = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tagButtons.forEach(button => on(button, 'click', onClick))
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
const e = Element.prototype
|
|
||||||
if (!e.matches) {
|
|
||||||
e.matches =
|
|
||||||
e.matchesSelector || e.msMatchesSelector || e.webkitMatchesSelector || e.mozMatchesSelector
|
|
||||||
}
|
|
||||||
if (!e.closest) {
|
|
||||||
e.closest = function(s) {
|
|
||||||
var el = this
|
|
||||||
if (!document.documentElement.contains(el)) return null
|
|
||||||
do {
|
|
||||||
if (el.matches(s)) return el
|
|
||||||
el = el.parentElement || el.parentNode
|
|
||||||
} while (el !== null && el.nodeType === 1)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
export const select = (s, parent = document) => parent.querySelector(s)
|
|
||||||
|
|
||||||
export const selectAll = (s, parent = document) => [].slice.call(parent.querySelectorAll(s))
|
|
||||||
|
|
||||||
export const scrollY = () => window.scrollY || window.pageYOffset
|
|
||||||
|
|
||||||
export const easeOutQuint = (t, b, c, d) => c * ((t = t / d - 1) * t ** 4 + 1) + b
|
|
||||||
|
|
||||||
export const on = (el, evt, fn, opts = {}) => {
|
|
||||||
const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e)
|
|
||||||
el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false)
|
|
||||||
if (opts.target) return delegatorFn
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createEventHub = () => ({
|
|
||||||
hub: Object.create(null),
|
|
||||||
emit(event, data) {
|
|
||||||
;(this.hub[event] || []).forEach(handler => handler(data))
|
|
||||||
},
|
|
||||||
on(event, handler) {
|
|
||||||
if (!this.hub[event]) this.hub[event] = []
|
|
||||||
this.hub[event].push(handler)
|
|
||||||
},
|
|
||||||
off(event, handler) {
|
|
||||||
const i = (this.hub[event] || []).findIndex(h => h === handler)
|
|
||||||
if (i > -1) this.hub[event].splice(i, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
window.EventHub = createEventHub()
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make iOS behave normally.
|
|
||||||
*/
|
|
||||||
if (/iPhone|iPad|iPod/.test(navigator.platform) && !window.MSStream) {
|
|
||||||
document.body.style.cursor = 'pointer'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/Mac/.test(navigator.platform)) {
|
|
||||||
document.documentElement.classList.add('macOS')
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A small utility to fix the letter kerning on macOS Chrome and Firefox when using the system font
|
|
||||||
* (San Francisco). It is now fixed in the text rendering engine in FF 58 and Chrome 64.
|
|
||||||
* UPDATE: It appears the applied fix doesn't work when the font is in italics. New fix has been added.
|
|
||||||
* Must be applied to all browsers for now.
|
|
||||||
*/
|
|
||||||
;(() => {
|
|
||||||
const ua = navigator.userAgent
|
|
||||||
|
|
||||||
// macOS 10.11 (El Capitan) came with San Francisco. Previous versions used Helvetica
|
|
||||||
const isRelevantMacOS =
|
|
||||||
/Mac/.test(navigator.platform) && (ua.match(/OS X 10[._](\d{1,2})/) || [])[1] >= 11
|
|
||||||
|
|
||||||
// Chrome v64 and FF v58 fix the issue
|
|
||||||
const isAffectedBrowser =
|
|
||||||
(ua.match(/Chrome\/(\d+)\./) || [])[1] < 64 || (ua.match(/Firefox\/(\d+)\./) || [])[1] < 58
|
|
||||||
|
|
||||||
const allEls = [].slice.call(document.querySelectorAll('*'))
|
|
||||||
|
|
||||||
if (isRelevantMacOS && isAffectedBrowser) {
|
|
||||||
document.documentElement.style.letterSpacing = '-0.3px'
|
|
||||||
allEls.forEach(el => {
|
|
||||||
const fontSize = parseFloat(getComputedStyle(el).fontSize)
|
|
||||||
if (fontSize >= 20) el.style.letterSpacing = '0.3px'
|
|
||||||
})
|
|
||||||
} else if (isRelevantMacOS && !isAffectedBrowser) {
|
|
||||||
// Italics fix
|
|
||||||
allEls.forEach(el => {
|
|
||||||
const { fontSize, fontStyle } = getComputedStyle(el)
|
|
||||||
if (fontStyle === 'italic') {
|
|
||||||
el.style.letterSpacing = parseFloat(fontSize) >= 20 ? '0.3px' : '-0.3px'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
// Deps
|
|
||||||
import 'focus-visible'
|
|
||||||
import 'normalize.css'
|
|
||||||
import 'prismjs'
|
|
||||||
import feather from 'feather-icons'
|
|
||||||
feather.replace()
|
|
||||||
|
|
||||||
// CSS
|
|
||||||
import '../css/deps/prism.css'
|
|
||||||
import '../css/index.scss'
|
|
||||||
|
|
||||||
// Polyfills
|
|
||||||
import './deps/polyfills'
|
|
||||||
|
|
||||||
// Components
|
|
||||||
import Sidebar from './components/Sidebar'
|
|
||||||
import BackToTopButton from './components/BackToTopButton'
|
|
||||||
import Tag from './components/Tag'
|
|
||||||
import Snippet from './components/Snippet'
|
|
||||||
import CodepenCopy from './components/CodepenCopy'
|
|
||||||
3
src/static-parts/README-end.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
_This README is built using [markdown-builder](https://github.com/30-seconds/markdown-builder)._
|
||||||
22
src/static-parts/README-start.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# 30 Seconds of CSS
|
||||||
|
|
||||||
|
<a href="https://css.30secondsofcode.org" target="_blank"></a>
|
||||||
|
|
||||||
|
[](https://github.com/30-seconds/30-seconds-of-css/blob/master/LICENSE) [](http://makeapullrequest.com) [](https://insight.io/github.com/30-seconds/30-seconds-of-css/tree/master/?source=0)
|
||||||
|
|
||||||
|
A curated collection of useful CSS snippets you can understand in 30 seconds or less.
|
||||||
|
Inspired by [30 seconds of code](https://github.com/30-seconds/30-seconds-of-code).
|
||||||
|
|
||||||
|
## View online
|
||||||
|
|
||||||
|
https://css.30secondsofcode.org
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See CONTRIBUTING.md for the snippet template.
|
||||||
|
|
||||||
|
#### Related projects
|
||||||
|
|
||||||
|
- [30 Seconds of Code](https://30secondsofcode.org/)
|
||||||
|
- [30 Seconds of Interviews](https://30secondsofinterviews.org/)
|
||||||
|
- [30 Seconds of React](https://github.com/30-seconds/30-seconds-of-react)
|
||||||