Олег Мохов
templates/ └── index.html └── index.css
a {
color: red;
}
html,
body
{
margin: 0;
padding: 0;
width: 100%;
font-family: Arial, sans-serif;
}
header
{
position: relative;
border: 3px solid #000;
width: 952px;
height: 551px;
margin: 18px auto 0;
}
/* далее ещё 400 строчек кода */
/* сброс умолчаний */
/* общие стили */
/* шапка */
/* основная часть */
/* футер */
/* страница печати */
/* мобильная версия */
/* какие-то правки */
/* новая страница */
/* ещё какие-то правки */
/* стили новой шапки */
button/ └── button.html └── button.css └── button.ie.css └── button.js └── _hovered/ └── button_hovered.css └── button_hovered.png └── __icon/ └── button__icon.css └── _color/ └── button__icon_color_blue.css └── button__icon_color_red.css
common/ └── header/ └── header.css └── header.js
desktop/ └── header/ └── header.css
touch/ └── header/ └── header.css └── header.js
@import (common/header/header.css);
@import (desktop/header/header.css);
header.desktop.css
@import (common/header/header.css);
@import (touch/header/header.css);
header.touch.css
({
block: 'page'
})
index.bemjson.js
({
mustDeps: [
{ block: 'header' }
],
shouldDeps: [
{ block: 'button' },
{ block: 'icon', mods: ['warning', 'error'] }
]
})
page.deps.js
res.render('template', data);
Данные
↓
HTML
Данные
↓
БЭМ-дерево
↓
HTML
{
block: 'page'
}
{
block: 'page',
mods: { type: 'main' }
}
{
block: 'page',
mods: { type: 'main' },
content: {
block: 'header'
}
}
«языки программирования, в которых описывается процесс вычисления в виде инструкций, изменяющих состояние программы (состояние памяти, состояние переменных...)»
«языки высокого уровня, в которых не задается пошаговый алгоритм решения задачи ("как" решить задачу), а описывается, "что" требуется получить в качестве результата»
bh.match('page', (ctx) => {
ctx.tag('main');
});
bh.match('page', (ctx) => {
ctx.content({
elem: 'content',
content: ctx.content()
});
});
bh.match('page', (ctx) => {
ctx.content([
{ elem: 'header' },
ctx.content(),
{ elem: 'footer' }
]);
});
bh.match('page__footer', (ctx) => {
ctx.content('THIS IS FOOOOTER!');
});
bh.match('page', (ctx) => {
ctx.content('CONTENT');
});
bh.match('page', (ctx) => {
ctx.tag('div');
});
Код
↓
Препроцессор
↓
CSS
.menu {
display: inline-block;
}
.menu__item {
background: #d0881d;
}
.menu__item:hover {
background: #ebb96f;
}
.menu__arrow {
background: #d0881d;
}
$bg_color = #d0881d;
.menu {
display: inline-block;
}
menu__item {
background: $bg_color;
}
.menu__item:hover {
background: lighten($bg_color, 40%);
}
.menu__arrow {
background: $bg_color;
}
.menu {
display: inline-block;
}
.menu__item {
background: #d0881d;
}
.menu__item:hover {
background: #ebb96f;
}
.menu__arrow {
background: #d0881d;
}
$bg_color = #d0881d;
.menu {
display: inline-block;
}
menu__item {
background: $bg_color;
}
.menu__item:hover {
background: lighten($bg_color, 40%);
}
.menu__arrow {
background: $bg_color;
}
.menu {
display: inline-block;
}
.menu__item {
background: #d0881d;
}
.menu__item:hover {
background: #ebb96f;
}
.menu__arrow {
background: #d0881d;
}
$bg_color = #d0881d;
.menu {
display: inline-block;
&__item {
background: $bg_color;
&:hover {
background: lighten($bg_color, 40%);
}
}
&__arrow {
background: $bg_color;
}
}
.menu {
display: inline-block;
}
.menu__item {
background: #d0881d;
}
.menu__item:hover {
background: #ebb96f;
}
.menu__arrow {
background: #d0881d;
}
$bg_color = #d0881d;
.menu {
display: inline-block;
&__item {
background: $bg_color;
&:hover {
background: lighten($bg_color, 40%);
}
}
&__arrow {
background: $bg_color;
}
}
Less
Sass
Stylus
Установка
npm install stylus
Компиляция
stylus index.styl --out ./css/index.css
stylus --watch index.styl
$font = 14px Helvetica, sans-serif;
box_width = 30%;
box_height = 300px;
.block {
font: $font;
width: box_width;
height: box_height;
}
.block {
font: 14px Helvetica, sans-serif;
width: 30%;
height: 300px;
}
$box_width = 300px;
$box_height = $box_width * 2;
.box {
width: $box_width;
height: $box_height;
}
.box {
width: 300px;
height: 600px;
}
.header {
.title {
font-size: 20px;
}
.link {
color: green;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
.header .title {
font-size: 20px;
}
.header .link {
color: #008000;
text-decoration: none;
}
.header .link:hover {
text-decoration: underline;
}
.header {
&__title {
font-size: 20px;
}
&__link {
color: green;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
.header__title {
font-size: 20px;
}
.header__link {
color: #008000;
text-decoration: none;
}
.header__link:hover {
text-decoration: underline;
}
$col_list = 1 2 3 4;
for $col in $col_list { td:nth-child({$col}) { width: 10% * $col; } }
for $col in (1..4) {...}
td:nth-child(1) {
width: 10%;
}
td:nth-child(2) {
width: 20%;
}
td:nth-child(3) {
width: 30%;
}
td:nth-child(4) {
width: 40%;
}
$cats = { cat_1: './images/cat1.jpg', cat_2: './images/cat2.jpg' }
$cats.cat_1 = './images/cat1_new.jpg'; $cats['cat_3'] = './images/cat3.jpg';
for $name, $bg_img in $cats { #img-{$name} { background: url($bg_img); } }
#img-cat1 {
background: url("./images/cat1_new.jpg");
}
#img-cat2 {
background: url("./images/cat2.jpg");
}
#img-cat3 {
background: url("./images/cat3.jpg");
}
$theme = 'day';
.sky {
if $theme == 'day' {
background: blue;
background-image: url(sun.png);
} else {
background: black;
background-image: url(stars.png);
}
}
.sky {
background: #00f;
background-image: url(sun.png);
}
@import 'theme'
// theme_day.styl
$bg_color = blue;
$bg_img = sun.png;
// main.styl
@import 'theme_day'
.sky {
background: $bg_color;
background-image: url($bg_img);
}
/* main.css */
.sky {
background: #00f;
background-image: url(sun.png);
}
set_bg_color($theme) {
if $theme == 'day' {
background: blue;
background-image: url(sun.png);
} else {
background: black;
background-image: url(stars.png);
}
}
.sky {
set_bg_color('night');
}
.sky {
background: #000;
background-image: url(stars.png);
}
npm install nib
@import 'nib'
@import 'nib/gradients' @import 'nib/buttons'
body {
background linear-gradient(bottom left, 80% white, blue, red)
}
body {
background: -webkit-linear-gradient(bottom left, #fff 80%, #00f, #f00);
background: -moz-linear-gradient(bottom left, #fff 80%, #00f, #f00);
background: -o-linear-gradient(bottom left, #fff 80%, #00f, #f00);
background: -ms-linear-gradient(bottom left, #fff 80%, #00f, #f00);
background: linear-gradient(to top right, #fff 80%, #00f, #f00);
}
#back-to-top {
fixed bottom 10px right 5px
}
#back-to-top {
position: fixed;
bottom: 10px;
right: 5px;
}
.animate-item {
animation-delay 1s;
animation-duration 1s;
}
.animate-item {
-webkit-animation-delay: 1s;
-moz-animation-delay: 1s;
-o-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
}
#logo {
image '/images/logo.main.png'
}
#logo {
background-image: url(/images/logo.main.png);
}
@media all and (-webkit-min-device-pixel-ratio: 1.5) {
#logo {
background-image: url(/images/logo.main@2x.png);
background-size: auto auto;
}
}
// Очень содержательный комментарий
/*
Длинный содержательный комментарий
*/
source maps
stylus index.styl -m
{
"version": 3,
"sources": ["index.styl"],
"names": [],
"mappings": "AA2BQ;EACI,YAAwB,kCAAxB;EACA,iBAAiB,KAAjB...
"file": "index.css"
}
CSS
Парсер
АSТ
↓
Плагины
↓
toString
↓
CSS
PostCSS
npm install postcss
npm install autoprefixer
Запуск
postcss --use autoprefixer -c options.json -o main.css css/*.css
{
"autoprefixer": {
"browsers": "> 5%"
}
}
{
"autoprefixer": {
"browsers": "Firefox > 20, last 2 Chrome versions"
}
}
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
}
]
},
postcss: function () {
return [require('autoprefixer'), require('precss')];
}
}
.box {
transition: transform 1s
}
.box {
-webkit-transition: -webkit-transform 1s;
transition: -ms-transform 1s;
transition: transform 1s
}
.box {
border-bottom: 1px solid rgb(200);
background: #20;
color: #f;
box-shadow: 0 1px 5px rgba(0, 0.5);
}
.box {
border-bottom: 1px solid rgb(200, 200, 200);
background: #202020;
color: #fff;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
}
.one {
size: 20px 10px;
}
.two {
size: 10px;
}
.one {
width: 20px;
height: 10px;
}
.two {
width: 10px;
height: 10px;
}
.comment {
background: url(images/sprite/ico-comment.png) no-repeat 0 0;
}
.bubble {
background: url(images/sprite/ico-bubble.png) no-repeat 0 0;
}
.comment {
background-image: url(images/sprite.png);
background-position: 0 0;
}
.bubble {
background-image: url(images/sprite.png);
background-position: 0 -50px;
}
body {
font-family: "Alice";
}
@font-face {
font-family: "Alice";
font-style: normal;
font-weight: 400;
src: local("Alice"), local("Alice-Regular"),
url("http://fonts.gstatic.com/s/alice/v7/sZyKh5NKrCk1xkCk_F1S8A.eot?#") format("eot"),
url("http://fonts.gstatic.com/s/alice/v7/l5RFQT5MQiajQkFxjDLySg.woff2") format("woff2"),
url("http://fonts.gstatic.com/s/alice/v7/_H4kMcdhHr0B8RDaQcqpTA.woff") format("woff"),
url("http://fonts.gstatic.com/s/alice/v7/acf9XsUhgp1k2j79ATk2cw.ttf") format("truetype")
}
body {
font-family: "Alice";
}
@b nav {
@e item {
display: inline-block;
}
@m placement_header {
background-color: red;
}
}
.nav__item {
display: inline-block;
}
.nav_placement_header {
background-color: red;
}
h1::before, h1:before {
margin: 10px 20px 10px 20px;
color: #ff0000;
-webkit-border-radius: 16px;
border-radius: 16px;
font-weight: normal;
font-weight: normal;
}
/* invalid placement */
@charset "utf-8";
@charset "utf-8";h1:before{margin:10px 20px;
color:red;border-radius:1pc;font-weight:400}
nav :any-link > span {
background-color: yellow;
}
nav :link > span,
nav :visited > span {
background-color: yellow;
}
.rating-star:matches(:first-child, .special) {
color: red;
}
.rating-star:first-child, .rating-star.special {
color: red;
}
.rgbaFallback {
background: rgba(0,0,0,0.5);
}
.rgbaFallback {
background: #000000;
background: rgba(0,0,0,0.5);
}
.opacityFallback {
opacity: 0.5;
}
.opacityFallback {
opacity: 0.5;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
}
body {
font-size: 16px;
}
.remFallback {
height: 10rem;
font: 2rem Arial;
}
body {
font-size: 16px;
}
.remFallback {
height: 160px;
height: 10rem;
font: 32px Arial;
font: 2rem Arial;
}
«Method of declaring a portion of reusable markup that is parsed but not rendered until cloned»http://caniuse.com/#feat=template
var template = document.querySelector('#template1');
document.body.appendChild(template.cloneNode(true));
...
...
...
...
...
...
...
...
...
class MyElement extends HTMLElement {
constructor () {
super();
}
};
customElements.define('my-element', MyElement);
connectedCallback // экземпляр элемента добавлен в документ
disconnectedCallback // экземпляр элемента удалён из документа
attributeChangedCallback(attrName, oldVal, newVal) // добавление/удаление/изменение аттрибута attrName
class ColorViewer extends HTMLElement {
constructor () {
super();
}
connectedCallback() {
this._color = this.getAttribute('color') || '#000';
this._colorInputElement = document.createElement('input');
this._colorInputElement.setAttribute('type', 'text');
this._colorInputElement.setAttribute('value', this._color);
this.appendChild(this._colorInputElement);
this._colorViewElement = document.createElement('div');
this._colorViewElement.style.background = this._color;
this.appendChild(this._colorViewElement);
}
};
customElements.define('color-viewer', ColorViewer);
class ColorViewer extends HTMLElement {
constructor () {
super();
}
connectedCallback() {
this._colorInputElement = document.createElement('input');
this._colorViewElement = document.createElement('div');
this._pickColor();
this.appendChild(this._colorInputElement);
this.appendChild(this._colorViewElement);
}
_pickColor() {
this._color = this.getAttribute('color') || '#000';
this._colorInputElement.setAttribute('type', 'text');
this._colorInputElement.setAttribute('value', this._color);
this._colorViewElement.style.background = this._color;
}
};
customElements.define('color-viewer', ColorViewer);
class ColorViewer extends HTMLElement {
static get observedAttributes() {
return ['color'];
}
constructor () {
super();
}
connectedCallback() { /* ... */ }
_pickColor() { /* ... */ }
attributeChangedCallback() {
this._pickColor();
}
};
customElements.define('color-viewer', ColorViewer);
Demo
class ColorViewer extends HTMLElement {
static get observedAttributes() { /* ... */}
constructor () { /* ... */ }
connectedCallback() {
/* ... */
this._colorInputElement
.addEventListener('keyup', this._onInputChange.bind(this));
}
_pickColor() { /* ... */ }
attributeChangedCallback() { /* ... */ }
_onInputChange () {
this.setAttribute('color', this._colorInputElement.value);
}
};
customElements.define('color-viewer', ColorViewer);
var shadow = element.attachShadow({mode: 'open'});
shadow.innerHTML = "Ололо";
document.registerElement('my-element', {prototype: Shadow});
var Shadow = Object.create(HTMLElement.prototype);
Shadow.createdCallback = function() {
var shadow = this.createShadowRoot();
var template = document
.querySelector('template#myTemplate');
shadow.appendChild(template.content);
};
document.registerElement('my-element', {
prototype: Shadow
});
<head>
</head>