.NET Fest: полная программа конференции на сайте. Присоединяйся к самому большому .NET ивенту
×Закрыть

Впорядковуємо класи Bootstrap

Bootstrap — чудовий фреймворк. Передусім, його перевага у швидкості створення інтерфейсу сайтів. Для мене як програміста він ідеально підходить для адмінок. Мало хто з замовників погодиться виділити кошти на професійний дизайн не тільки для основного сайту, а ще й для панелі керування. До того ж, Bootstrap дуже допомагає мені створювати нові сайти. Коли дизайну для нового сайту ще немає, а споглядання «голих» елементів HTML пригнічує, Bootstrap допомагає вирішити цілий ряд проблем.

Марк Отто та Джейкоб Торнтон — творці Bootstrap

По-перше, він гарний. Його, на відміну від власного дизайну, зімпровізованого під час створення сайту, не соромно показати людям. По-друге, розробка з допомогою Bootstrap типових й невибагливих сайтів значною мірою економить час та дозволяє зосереджуватись саме на програмуванні.

Фейкові класи

На жаль, найбільша перевага Bootstrap, швидкість розроблення, автоматично породжує недолік — складність підтримки. Ця проблема виникає через використання класів для зміни лише однієї-двох властивостей стилю. Я називаю ці класи модним зараз словом «фейкові». Цю проблему легше показати на прикладі, що базується на фрагменті коду, який я взяв зі сторінки зі зразками на офіційному сайті Bootstrap.

<div class="jumbotron p-4 p-md-5 text-white rounded bg-dark">
    <div class="col-md-6 px-0">
        <h1 class="display-4 font-italic">Title of a longer featured blog post</h1>
        <p class="lead my-3">Multiple lines of text that form the lede, informing new readers quickly and efficiently about what’s most interesting in this post’s contents.</p>
        <p class="lead mb-0">
            <a href="#" class="text-white font-weight-bold">Continue reading...</a>
        </p>
    </div>
</div>

Єдиний «справжній» клас в цьому прикладі — це jumbotron, всі решта — «фейкові». Для того, щоб краще зрозуміти, про що йдеться, я приблизно «перекладу» попередній приклад на більш зрозумілу для всіх мову стилів.

<div class="jumbotron" style="padding: 3rem; color: #fff; border-radius: .25rem; background-color: #343a40;">
    <div style="flex: 0 0 50%; max-width: 50%; padding-left: 0; padding-right: 0;">
        <h1 style="font-size: 3.5rem; font-style: italic;">Title of a longer featured blog post</h1>
        <p style="font-size: 1.25rem; font-weight: 300; margin-top: 1rem; margin-bottom: 1rem;">Multiple lines of text that form the lede, informing new readers quickly and efficiently about what’s most interesting in this post’s contents.</p>
        <p style="font-size: 1.25rem; font-weight: 300; margin-bottom: 0;">
            <a href="#" style="color: #fff; font-weight: 700;">Continue reading...</a>
        </p>
    </div>
</div>

Зрозуміло, що верстати шаблон для сайту буде суттєво швидше, якщо стилі документа писати не в окремий css-файл, а відразу в елементи документа. Та ще й використовуючи зручні скорочення на кшталт mt-1 замість довгого margin-top: 0.25rem;. Але чому ніхто не подумав про те, наскільки складно його потім буде підтримувати? Це особливо прикро, коли при створенні сайту намагаєшся максимально точно дотримуватись MVC-шаблону.

Наведу ще декілька прикладів з фрагментами коду зі html-сторінок офіційного сайту Bootstrap, в яких часто використовуються «фейкові» класи.

<!-- https://getbootstrap.com/docs/4.3/examples/pricing/ -->
<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">...</div>

<!-- https://getbootstrap.com/docs/4.3/examples/product/ -->
<div class="bg-dark mr-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center text-white overflow-hidden">...</div>

<!-- https://getbootstrap.com/docs/4.3/examples/blog/ -->
<div class="row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">...</div>

<!-- https://getbootstrap.com/docs/4.3/examples/dashboard/ -->
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">...</div>

<!-- https://getbootstrap.com/docs/4.3/examples/offcanvas/ -->
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-purple rounded shadow-sm">...</div>

Цей випадок нагадав мені ще студентський підхід ЗЗЗ — «Завчив, Здав, Забув». Під’єднав фреймворк, швидко зверстав, здав замовнику та й забув про нього. А страждає з ним нехай хтось інший.

Я пропоную відволіктись на деякий час від Bootstrap та завітати на сторінку специфікації HTML5. А якщо бути точнішим — в розділ 1.10.1. Presentational markup. І якщо Google Перекладач не дуже сильно помилився, то зміст передостаннього параграфа цього розділу виглядає приблизно так:

Єдині функції презентаційної розмітки, що залишилися в HTML, є атрибут style та елемент <style>.

Використання атрибута style не рекомендується у виробничих середовищах, але він може бути корисним для швидкого прототипування (де його правила пізніше можуть бути переміщені безпосередньо в окремі таблиці стилів) і для надання конкретних стилів у незвичайних випадках, коли реалізація окремою таблицею стилів буде недоцільною.

Аналогічно, елемент <style> може бути корисним тільки для стилів, специфічних для певної сторінки або в поєднанні з ними, але зовнішня таблиця стилів буде більш доцільною, коли стилі застосовуються до декількох сторінок.

А тепер повернімось до нашого коду та подивимось, як він мав би виглядати, якщо б його створювали згідно з рекомендаціями.

<div class="jumbotron">
    <div class="jumbotron-container">
        <h1 class="jumbotron-title">Title of a longer featured blog post</h1>
        <p class="jumbotron-description">Multiple lines of text that form the lede, informing new readers quickly and efficiently about what’s most interesting in this post’s contents.</p>
        <p class="jumbotron-link">
            <a href="#">Continue reading...</a>
        </p>
    </div>
</div>

За такої умови, всі стилі мали б визначатись за допомогою зовнішньої таблиці стилів так, як це радять в специфікації HTML5.

.jumbotron {padding: 3rem; color: #fff; border-radius: .25rem; background-color: #343a40;}
.jumbotron-container {flex: 0 0 50%; max-width: 50%; padding-left: 0; padding-right: 0;}
.jumbotron-title {font-size: 3.5rem; font-style: italic;}
.jumbotron-description {font-size: 1.25rem; font-weight: 300; margin-top: 1rem; margin-bottom: 1rem;}
.jumbotron-link {font-size: 1.25rem; font-weight: 300; margin-bottom: 0;}
.jumbotron-link a {color: #fff; font-weight: 700;}

Але не поспішайте радіти: такий спрощений підхід може створити вам багато додаткових проблем. Річ у тім, що більшість правил, винесених нами в окрему таблицю стилів, пов’язані з багатьма іншими елементами дизайну. А коли ми їх продублювали, то порушили цей зв’язок з фреймворком. І якщо в майбутньому, з тих чи інших причин, якась властивість в самому фреймворку зміниться, то її додатково буде необхідно змінювати всюди в файлі стилів.

Ця проблема подібна до проблеми «copy-paste» значного шматка коду в програмуванні. І якщо дизайнери-верстальники, яким необхідно швидко здати проект, ще можуть дозволити собі особливо не перейматись цим питанням, то для програмістів, які будуть довгий час цей проект підтримувати та розвивати, таке рішення є абсолютно неприйнятним.

Наслідування класів

Але нам поталанило: мало того, що Bootstrap розповсюджується з відкритим початковим кодом, так ще й в четвертій версії він реалізований за допомогою метамови SCSS. А такий підхід дає розробникам багато додаткових можливостей для більш гнучкого його використання. Декілька з цих можливостей ми якраз і використаємо для розв’язання проблеми з «фейковими» класами.
Я переконаний, що вносити зміни в файли фреймворку — не найвдаліше рішення. Краще імпортувати стилі Bootstrap у свій власний додатковий файл, а вже в ньому можна робити що завгодно: додавати власні нові правила чи перевантажувати наявні. Пізніше ми без проблем зможемо оновлювати оригінальні файли фреймворку на новіші, не забуваючи заново перетранслювати scss-файл.

Отож, створимо файл з назвою, наприклад, bootstrap-extend.scss та з одним-єдиним записом @import "bootstrap-4.3.1/scss/bootstrap";. У разі потреби шлях до scss-файлів фреймворку потрібно замінити на той, за яким він знаходиться конкретно у вашому проекті. Після трансляції цього файлу у вас має з’явитись файл bootstrap-extend.css, який необхідно прописати у свій html-файл. Теоретично, нова таблиця стилів має бути повністю аналогічна до такого ж готового файлу з фреймворку. Конкретно в мене, в мінімізованому вигляді, він виявився ще й на 10 КБ легший, в порівнянні з аналогічним оригінальним.

Якщо ви на своєму проекті використовуєте не всі складові Bootstrap, тоді вам необхідно прописувати для імпорту не загальний файл, як в моєму прикладі, а кожну необхідну частину фреймворку окремо. Подивитись повний перелік його складових частин можна в самому файлі, який я вказав в прикладі вище при імпорті.

А тепер найцікавіше — доповнимо фреймворк своїми правилами для стилів за допомогою метамови SCSS в новоствореному файлі, не руйнуючи водночас зв’язок з самим фреймворком. Для початку додамо такий код:

@each $name, $width in $container-max-widths {
  .mw-#{$name} {max-width: #{$width};}
}

Розв’язання проблеми цей код абсолютно не стосується, але я переконаний, що його дуже бракує в самому фреймворку. Завдяки цим декільком рядкам ви зможете обмежувати максимальну ширину елементів за допомогою прописування класів такого виду mw-sm або mw-md. Наприклад, якщо у вас буде таблиця з 2-3 вузькими стовпчиками і її розтягування на всю ширину контейнера псуватиме весь вигляд, використання одного з цих обмежувальних класів буде простим та елегантним рішенням.

А тепер додамо саме той код, який дозволить використовувати в HTML прийнятні класи.

.jumbotron {@extend .p-4, .p-md-5, .text-white, .rounded, .bg-dark;
    .jumbotron-container {@extend .col-md-6, .px-0;
        .jumbotron-title {@extend .display-4, .font-italic;}
        .jumbotron-description {@extend .lead, .my-3;}
        .jumbotron-link {@extend .lead, .mb-0;
            a {@extend .text-white, .font-weight-bold;}
        }
    }
}

За допомогою правила @extend метамови SCSS, ми використали множинне наслідування для створення необхідних стилів на основі наявних правил фреймворку. Оскільки «фейкові» класи змінюють, зазвичай, одну-дві властивості стилю, то у нас відсутні проблеми з суперечностями, характерними для цього типу наслідування. Водночас ми зберегли необхідний зв’язок з фреймворком, а сама html-сторінка повністю відповідає рекомендаціям специфікації сучасного стандарту HTML5.

Не менш вагомою додатковою перевагою такого підходу до використання стилів фреймворку є те, що ваш проект жорстко до нього не прив’язаний. Та коли настане час змінити дизайн на новий, достатньо буде замінити таблицю стилів без нудної та кропіткої заміни стилів в самому документі HTML.

Висновки

У мене складається враження, що люди, женучись за швидким результатом, забувають про зворотній бік медалі. Чим швидше ви намагаєтесь створити проект, тим складніше буде його розвивати та підтримувати. Як наслідок, роботодавцям доводиться підвищувати зарплати на вакансії, щоб хоч якось додатково вмотивувати потенційних працівників долучитись до проекту, який хтось створив дуже швидко та дешево.

Звичайно, трапляються замовлення на «сайти-одноденки», про які ви точно знаєте, що вони матимуть короткий «лайфтайм» та витрачати на них багато часу просто недоцільно. Але, зазвичай, такі поодинокі випадки не притаманні професійному середовищу.

LinkedIn

10 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

была статейка интересная почему 12-колонок проиграло современным гридам-флексам, потому что узко

1) Раздел Examples на сайте Bootstrap — осознанно презентационный, проф разработчики знают что нужно юзать @extend, ваш пример — правильный.
Но важно не забывать что в офф. документации Bootstrap 4 никаких презентационных класов нет: getbootstrap.com/...​4.3/components/jumbotron

Hello, world!

This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

It uses utility classes for typography and spacing to space content out within the larger container.

Learn more

2) Вообще перебивать базовые стили бутстрапа — плохой пример, правильно — кастомизировать предустановленные variables, установив свои перед !default стилями bootstrap

1) Приклад для статті з класом jumbotron я взяв з цієї сторінки

getbootstrap.com/docs/4.3/examples/blog

2) Я теж думав спочатку про variables, але тоді треба відстежувати, якщо в якийсь клас фреймворку з часом додадуть нове правило або заберуть наявне.

Ви же посилаєтася на бутстреп так: "bootstrap": "4.3.1"? Чи принаймні "bootstrap": "^4.3.1"? Туди вже ніхто нічого не додасть.
Pixel perfect з бутстрепом має мало спільного. Для чого Ви закликаєте в прототипі все виписувати до style=""? Що с тими style потым робити? Як з тої суміші потім вирізати спільні стилі?
Ви якось не так розумієте ідеологію бутсрепу.

Звідки така впевненість, що туди вже ніхто нічого не додасть? Фреймворк активно розвивається. Наприклад, в порівнянні з 4.0 багато чого додали.
Я не закликаю все вписувати в style="", а просто використав його для наглядної демонстрації класів фреймворку. Ви не уважно прочитали статтю.
А на рахунок Pixel perfect — нехай кожен сам собі обирає, що для нього краще в кожній конкретній ситуації. Я просто показав один з можливих шляхів.

Звідки така впевненість, що туди вже ніхто нічого не додасть

Ви користуєтесь npm (yarn)?

Тоді Вам той рядок мало шо скаже. Може так? <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> —
Якщо Ви референсуєте версію 4.3.1, то там(!) вже нічого і ніколи не зміниться
Щодо «фейкових» класів, я пропоную .fake { @extend .p-4, .p-md-5, .text-white, .rounded, .bg-dark }

Ви якось занадто буквально сприймаєте приклади зі статті. На момент її написання поточна версія Bootstrap 4.3.1. Тому я і використав її для прикладів. Через деякий час це може бути 4.3.8 або навіть 4.5. Але на проблему, описану в статті, це ніяк не впливає. Тільки замінити шлях до теки при імпорті, про що я написав трохи нижче.

На серйозних проектах міграція — то заздалегідь запланована активність, і далеко не кожен розробник має право змінювати версії. Думаю, що без нагальних потреб, версії живуть без змін мінімум — 2-3 роки.
Взагалі-то великі проекти переосмислюють бутсреп, усі його маржини, стилі, та тримаюсь власну версію (звісно ж сумісну з мажорною версією бутсрепа), де розташування елементів визначається певними правилами, тому «.p-4, .p-md-5, .text-white, .rounded, .bg-dark» там ніколи не зустрінеться в атрибутах елементу.
Лише як вийняток, який легше кидається в око, ніж коли то буде заховано в scss.

На MVP взагалі пофіг, яка версія.

На «маленьких сайтиках» — теж.

А @extend підтримую, як Ви помітили. Може, тільки невлучно висловився. Лише важко уявити, де його можна активно(!) використовувати. Як я кажу, справжні проекти «вдосконалять» тей jumbotron та визначать клас контейнера ще до того, як знадобиться mt-10. На закладі variables.

Подписаться на комментарии