Модульная верстка

Магомедов Исмаил
HAOS DEV

Верстка стала сложной

Верстка стала сложной

Адаптивность

Зоопарк браузеров

Новые API

Доступность

Обратная совместимость

Бизнес динамичен

Бизнес динамичен

Рост экосистемы

Меняются тренды в дизайне

Текучка кадров

Частый рефакторинг

Части интерфейса взаимосвязаны

Больше связей — выше сложность

Спустя полгода

Централизация и независимость

Слово «правки» не должно быть страшным

Компонент — функциональная единица интерфейса

1 компонент — 1 функция

Компонент - функциональная единица интерфейса

Компонент

Компонент - функциональная единица интерфейса

HTML

CSS

JS

CSS

CSS

Глобальное пространство имен

    
    .items-list {
        color: red;
        font-size: 16px;
    }

    ...

    .items-list {
        font-size: 12px;
    }

CSS

Разделение стилей

CSS > Методологии

BEM

OOCSS

SMACSS

Тысячи их

CSS > Методологии > BEM

Блок, элемент, модификатор


    .menu { font-size: 16px; }
    
    .menu__link { color: #ffc000; }

    .menu--large { font-size: 24px; }

    <div class="menu menu--large">
        <a href="..." class="menu__link">Click me!</a>
    </div>

CSS > Методологии > OOCSS

Object-oriented CSS


    .button { padding: 15px 30px; }
    
    .theme-red { color: red; }

    .theme-large { font-size: 24px; }

    <button class="button theme-red theme-large">
      Click me!
    </button>

CSS > Методологии > SMACSS

Scalable and Modular Architecture for CSS

  p {
    line-height: 1.5;
  }

  .layout {
    margin: 0 auto;
    max-width: 80vw;
  }

  .module {
    font-size: 18px;
  }

  .important {
    border: 2px solid red;
  }

  .text-red {
    color: red;
  }

  <div class="layout">

    <div class="module text-red">

      <p class="important">
        This messsage is important!
      </p>

    </div>

  </div>

CSS > Методологии > CSS Modules

  p {
    line-height: 1.5;
  }

  .layout {
    margin: 0 auto;
    max-width: 80vw;
  }

  .module {
    font-size: 18px;
  }

  .important {
    border: 2px solid red;
  }
  
  import css from './style.css'
    
  const App = () => 
    <div class={css.layout}>
      <div class={css.module}>
        <p class={css.important}>
          This messsage is important!
        </p>
      </div>
    </div>

CSS > Методологии > CSS Modules

  p {
    line-height: 1.5;
  }

  .layout_y6TR {
    margin: 0 auto;
    max-width: 80vw;
  }

  .module_u88r {
    font-size: 18px;
  }

  .important_OipL {
    border: 2px solid red;
  }
  



    <div class="layout_y6TR">
      <div class="module_u88R">
        <p class="important_OipL">
          This messsage is important!
        </p>
      </div>
    </div>

CSS

Модульность на уровне имен классов

CSS

Используем препроцессоры

  
    fontSize  = 16px
    mainColor = #f00

    .menu
      font-size: fontSize 
    
      &__link
        color: mainColor 

      &--large
        font-size: fontSize  * 1.5

Stylus

CSS

Используем препроцессоры

    
    mainColor = #f00

    button(radius)
      border: 2px solid mainColor
      border-radius: radius

    theme-red(fontSize)
      border-color: mainColor 
      color: darken(mainColor, 20%)

    .button
      button( 4px )
      
      &--red
        theme-red()
        
    
  .button {
    border: 2px solid #f00;
    border-radius: 4px;
  }

  .button--red {
    border-color: #f00;
    color: #c00;
  }
        

CSS

Используем сборщики

menu.styl

button.styl

etc.styl

style.styl

variables.styl

mixins.styl

Gulp.js / Webpack

style.css

HTML

HTML > Jade (pug)


  mixin menu()
    ul.menu
      li.menu__link: a(href="#1") Link #1
      li.menu__link: a(href="#2") Link #2

1 компонент — 1 миксин


  include menu.jade

  .container
    +menu()

HTML > Jade (pug)

   

  <div class="container">
    <ul class="menu">
      <li class="menu__link">
        <a href="#1">Link #1</a>
      </li>

      <li class="menu__link">
        <a href="#2">Link #2</a>
      </li>
    </ul>
  </div>

1 компонент — 1 миксин

HTML > Jade (pug)


  mixin button(text)
    .button= text

Миксин + параметры


  include button.jade

  .container
    +button('Click me!')
    +button('Click me again!')

HTML > Jade (pug)

   


  <div class="container">
    <div class="button">
      Click me!
    </div>

    <div class="button">
      Click me again!
    </div>
  </div>

Миксин + параметры

HTML > Jade (pug)


  mixin group(text)
    .group
      span= text
      {block}

Расширяемый миксин

  
  .container
    +group('Group one')
      img(src='one.jpg')
      span Additional content

HTML > Jade (pug)

   

  <div class="container">
    <div class="group">
      <span>Group one</span>
      
      <img src="one.jpg">

      <span>Additional content</span>
    </div>
  </div>

Расширяемый миксин

CSS

Используем сборщики

menu.jade

button.jade

etc.jade

index.jade

Gulp.js / Webpack

index.html

HTML > Jade (pug)

Храним разметку раздельно

Сокращаем количество кода

JS-функции внутри

Данные не привязаны к блоку

Собираем страницы по частям

JavaScript

JavaScript > ООП


  var Slider = (function(options) {
    this.selector  = options.selector || '.slider';
    this.nextSlide = function() {...}
    this.goToSlide = function(slideNumber) {...}

    return {
      switchSlide: this.goToSlide
    }
  }());

  var slider = new Slider({
    selector: '.main-slider'
  });

  slider.switchSlide(3);

Паттерн "Модуль"

JavaScript > ООП


  class Slider {
    constructor(options) {
      this.selector = options.selector || '.slider';
    }
  
    nextSlide() { ... }
    prevSlide() { ... }
    goToSlide(slideNumber) { ... }
  }

  var slider = new Slider({
    selector: '.main-slider'
  });

  slider.goToSlide(3);

Классы ES6

JavaScript > Фреймворки

Polymer

React

Vue

Angular 2

Ember

JavaScript > Фреймворки

<CustomComponent />

Styles

Template

Model

JavaScript > Фреймворки > React

  import React      from 'react'

  import Pagination from './components/pagination'
  import ListItems  from './components/ListItems'

  class AdsList extends React.Component {
    // Some code

    render(
      <div>
        <ListItems model={this.state.model} />
  
        <Pagination amount="40" limit="5" />
      </div>
    )
  }
  import React from 'react'
  import css   from './style.css'

  export class Pagination extends React.Component {
    // Some code

    render(
      <div className={css.pagination}>
        <nav>
          {
            ...
            return <a href="page/1">Page 1</a>
          }
        </nav>
      </div>
    )
  }

JavaScript > Фреймворки > React

Redux

JavaScript > Фреймворки > React

Store

Использование модулей

Пространство обретает форму благодаря

контенту и контексту

Negative Space

Negative Space

Пространство в верстке

Пространство в верстке

Пространство в верстке

Блочная модель

400 x 300px

40px

40px

50px

50px

500 x 380px

Пространство в верстке

box-sizing: border-box

300 x 280px

40px

40px

50px

50px

400 x 300px

Как это сделать?

Модульные сетки

bootstrap, flexbox-grid и т.д.

Flexbox

CSS grid layout

@media считает только размеры окна

cq-prolyfill

  
  <script src="cq-prolyfill.js"></script>
.menu:container("width > 500px") {
   font-size: 18px;
}

.menu:container("width < 500px") {
   font-size: 14px;
}

cs-prolyfill

Итоги

Компонент - самостоятельная единица интерфейса

Быстрое проектирование и редактирование

Упрощение командной работы

Компоненты не формируют контекст

Структура компонента

(1 css, 1 html, 1 js)

Статьи

Видео

Изолируем компоненты в CSS (Андрей Ситник)

ВОПРОСЫ?

Модульная верстка

By Исмаил

Модульная верстка

что такое компоненты, почему это важно, как разрабатывать компоненты и использовать их в работе

  • 690