Создайте свою систему дизайна, Кнопки Создайте свою систему дизайна, Кнопки



Кнопки - это наиболее важные интерактивные компоненты, используемые пользователями для выполнения действий. Проектирование кнопок означает создание инструментария, позволяющего взаимодействовать с интерфейсом.

В этой заключительной статье нашей серии о системах проектирования мы рассмотрим, как создать систему кнопок в CSS.

 

Настройка основного стиля кнопки

Отправной точкой проектирования кнопок в CSS является определение базового стиля, который можно применить ко всем компонентам кнопок:

:root {
    --btn-font-size: 1em;
    --btn-radius: 0.25em;
}

.btn {
    display: inline-flex;
    position: relative;
    white-space: nowrap;
    text-decoration: none;
    line-height: 1;

    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--btn-radius);
    font-size: var(--btn-font-size);
    color: var(--color-link);
}

Основной стиль включает те свойства, которые вы не планируете переписывать, создавая в дальнейшем варианты кнопок, а также стиль сброса, чтобы предотвратить общие проблемы стиля. Например:

position: relative; используется, если вы хотите создать интерактивные значки, где значок заменяет текстовую метку.
white-space: nowrap; предотвращает перенос текстовой метки на следующую строку.
text-decoration: none; удаляет текстовое украшение, если вы применяете класс .btn к ссылке.

Абстрагирование размера шрифта и радиуса границы особенно полезно на ранних этапах создания системы проектирования, когда часто происходят изменения. Значения заполнения задаются в соответствии с нашей системой интервалов, так что они автоматически реагируют.

 

Варианты стиля

Варианты стиля - это разные стили, используемые для передачи значений кнопкам. Они обычно включают:

.btn - primary → основной стиль кнопки вызова к действию.
.btn--secondary → тонкая версия стиля, используемая для вторичных действий или в комбинации с кнопкой основного / акцент.
.btn--accent → используется для привлечения внимания к кнопке (например, деструктивные действия).
.btn [disabled] → используется для обратной связи, чтобы определить кнопку, которая отключена.

Создайте свою систему дизайна, Кнопки

/* themes */
.btn--primary {
    // main button
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-label);
    @include fontSmooth;

    &:visited {
        color: var(--btn-primary-label);
    }

    &:hover {
        background-color: var(--btn-primary-hover);
    }

    &:active {
        background-color: var(--btn-primary-active);
    }
}

.btn--secondary {
    // subtle version, used for secondary actions or in combo with primary/accent button
    background-color: var(--btn-secondary-bg);
    color: var(--btn-secondary-label);

    &:visited {
        color: var(--btn-secondary-label);
    }

    &:active {
        background-color: var(--btn-secondary-active);
    }
}

.btn--accent {
    // used to draw special attention to the button (e.g. destructive actions)
    background-color: var(--btn-accent-bg);
    color: var(--btn-accent-label);
    @include fontSmooth;

    &:visited {
        color: var(--btn-accent-label);
    }

    &:hover {
        background-color: var(--btn-accent-hover);
    }

    &:active {
        background-color: var(--btn-accent-active);
    }
}

/* feedback */
.btn[disabled] {
    cursor: not-allowed;
    background-color: var(--btn-disabled-bg);
    color: var(--btn-disabled-label);
    box-shadow: none;
    opacity: 0.6;

    &:visited {
        color: var(--btn-disabled-label);
    }
}

Несколько важных замечаний: во-первых, все цвета определены в отдельном файле _colors.scss. Работая над нашей картой, мы решили иметь единственный источник правды, хранящий все цвета и темы. Для получения дополнительной информации вы можете проверить нашу статью по этой теме.

Вот загляните, как цвета кнопок определены в нашем файле _colors.scss:

/* --------------------------------
Colors
-------------------------------- */

:root {
    /* main colors */
    --color-primary: #286bf4;
    --color-primary-light: color-mod(var(--color-primary) tint(15%));
    --color-primary-dark: color-mod(var(--color-primary) shade(15%));
    --color-primary-bg: color-mod(var(--color-primary) alpha(20%));

    --color-accent: #f5414f;
    --color-accent-light: color-mod(var(--color-accent) tint(15%));
    --color-accent-dark: color-mod(var(--color-accent) shade(10%));
    --color-accent-bg: color-mod(var(--color-accent) alpha(20%));

    /* shades - generated using chroma.js - 12 steps */
    --black: #1d1d21;
    --gray-10: #2e2e31;
    --gray-6: #7b7a7d;
    --gray-4: #a5a5a6;
    --gray-3: #bbbbbc;
    --gray-2: #d1d0d2;
    --gray-1: #e8e7e8;
    --white: white;

    /* buttons */
    --btn-primary-bg: var(--color-primary);
    --btn-primary-hover: var(--color-primary-light);
    --btn-primary-active: var(--color-primary-dark);
    --btn-primary-label: var(--white);

    --btn-secondary-bg: var(--gray-1);
    --btn-secondary-active: var(--gray-2);
    --btn-secondary-label: var(--gray-10);

    --btn-accent-bg: var(--color-accent);
    --btn-accent-hover: var(--color-accent-light);
    --btn-accent-active: var(--color-accent-dark);
    --btn-accent-label: var(--white);

    --btn-disabled-bg: var(--gray-2);
    --btn-disabled-label: var(--gray-10);
}

Смеситель fontSmooth используется для улучшения рендеринга шрифтов, когда светлый текст используется на темном фоне. В наше время этот стиль применяется ко всем элементам HTML. После некоторых исследований мы решили создать mixin для ориентации на определенные элементы, а не включать этот стиль в наш глобальный файл _reset.scss.

// edit font rendering -> tip: use for light text on dark backgrounds
@mixin fontSmooth {
    -webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

Поскольку наша инфраструктура должна быть настраиваемой отправной точкой для любых веб-проектов, я старался не включать в нее какой-то несущественный стиль. Например, я не включал тени или эффекты фокусировки, потому что они будут отличаться в каждом проекте. Предоставление стиля по умолчанию заставило бы наших разработчиков инфраструктуры искать и перезаписывать вещи, а не иметь свободу основываться на вещах.

 

Варианты размеров

В дополнение к изменениям стиля, система кнопок также должна включать изменения размера. Чтобы быть ясным: я не имею в виду кнопки реагирования, которые применяются на разных контрольных точках, но для того, чтобы иметь классы утилит для создания кнопок разных размеров, независимо от размера видового экрана.

Хорошим подходом к созданию таких вариаций является определение переменных размера (с использованием функции CSS calc ()), а затем применение этих переменных к классам служебных данных размера:

:root {
    --btn-font-size: 1em;
    --btn-sm: calc(var(--btn-font-size) - 0.2em);
    --btn-md: calc(var(--btn-font-size) + 0.2em);
    --btn-lg: calc(var(--btn-font-size) + 0.4em);

    --btn-radius: var(--radius);
}

/* button size */
.btn--sm {
    font-size: var(--btn-sm);
}

.btn--md {
    font-size: var(--btn-md);
}

.btn--lg {
    font-size: var(--btn-lg);
}

.btn--full-width {
    display: flex;
    width: 100%;
    justify-content: center;
}

Создайте свою систему дизайна, Кнопки

 

Использование значков в кнопках

Мы используем класс .icon-text-aligner для выравнивания текстовых меток и значков в пределах кнопок:

<button class="btn btn--primary icon-text-aligner">
<span>Button</span>
<svg class="icon"><use href="#icon-arrow-right" xlink:href="#icon-arrow-right"/></svg>
</button>

Так как у нас может быть кнопка, которая не включает текст, а только значок, рекомендуется настроить таргетинг на .icon внутри базового класса .btn и убедиться, что значок наследует цвет по умолчанию на ярлыке кнопки (даже если метка не там):

.btn {
    display: inline-flex;
    position: relative;
    white-space: nowrap;
    text-decoration: none;
    line-height: 1;

    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--btn-radius);
    font-size: var(--btn-font-size);
    color: var(--color-link);

    transition: .2s;

    &:active {
        transition: none;
    }

    .icon {
        /* icon inherits color of button label */
        color: inherit;
        flex-shrink: 0;
    }
}

Создайте свою систему дизайна, Кнопки

 

Группы кнопок

Другим классическим вариантом использования в глобальном файле CSS является группа кнопок. К счастью, Flexbox упрощает установку кнопок в простой одномерной компоновке:

/* buttons group */
.btns {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: calc(-1 * var(--space-xs));

    > * {
        margin-right: var(--space-xs);
        margin-bottom: var(--space-xs);

        &:last-of-type {
            margin-right: 0;
        }
    }
}

 

Кнопки реагирования

Если вы до сих пор следовали нашим сериям по системам проектирования, вы знаете, что наш отзывчивый подход основан на двух переменных CSS: --text-base-size и -space-unit. Обновление этих переменных с помощью медиа-запросов создает каскадный эффект, который влияет на всю систему проектирования, включая кнопки.

В наших рамках компоненты кнопок, как и все другие компоненты, основаны на единицах, соответствующих единицам. Текущий размер шрифта обновляется переменной -text-base-size. Поэтому наши кнопки уже реагируют, поэтому нет необходимости создавать один мультимедийный запрос в файле _buttons.scss.

Создайте свою систему дизайна, Кнопки

 

_buttons.scss

Соединяя все это, вот наш глобальный файл SCSS для наших кнопок:

/* -------------------------------- 
Buttons
-------------------------------- */

:root {
    --btn-font-size: 1em;
    --btn-sm: calc(var(--btn-font-size) - 0.2em);
    --btn-md: calc(var(--btn-font-size) + 0.2em);
    --btn-lg: calc(var(--btn-font-size) + 0.4em);

    --btn-radius: var(--radius);
}

.btn {
    display: inline-flex;
    position: relative;
    white-space: nowrap;
    text-decoration: none;
    line-height: 1;

    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--btn-radius);
    font-size: var(--btn-font-size);
    color: var(--color-link);

    transition: .2s;

    &:active {
        transition: none;
    }

    .icon {
        /* icon inherits color of button label */
        color: inherit;
        flex-shrink: 0;
    }
}

/* themes */
.btn--primary {
    // main button
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-label);
    @include fontSmooth;

    &:visited {
        color: var(--btn-primary-label);
    }

    &:hover {
        background-color: var(--btn-primary-hover);
    }

    &:active {
        background-color: var(--btn-primary-active);
    }
}

.btn--secondary {
    // subtle version, used for secondary actions or in combo with primary/accent button
    background-color: var(--btn-secondary-bg);
    color: var(--btn-secondary-label);

    &:visited {
        color: var(--btn-secondary-label);
    }

    &:active {
        background-color: var(--btn-secondary-active);
    }
}

.btn--accent {
    // used to draw special attention to the button (e.g. destructive actions)
    background-color: var(--btn-accent-bg);
    color: var(--btn-accent-label);
    @include fontSmooth;

    &:visited {
        color: var(--btn-accent-label);
    }

    &:hover {
        background-color: var(--btn-accent-hover);
    }

    &:active {
        background-color: var(--btn-accent-active);
    }
}

/* feedback */
.btn[disabled] {
    cursor: not-allowed;
    background-color: var(--btn-disabled-bg);
    color: var(--btn-disabled-label);
    box-shadow: none;
    opacity: 0.6;

    &:visited {
        color: var(--btn-disabled-label);
    }
}

/* button size */
.btn--sm {
    font-size: var(--btn-sm);
}

.btn--md {
    font-size: var(--btn-md);
}

.btn--lg {
    font-size: var(--btn-lg);
}

.btn--full-width {
    display: flex;
    width: 100%;
    justify-content: center;
}

/* buttons group */
.btns {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: calc(-1 * var(--space-xs));

    > * {
        margin-right: var(--space-xs);
        margin-bottom: var(--space-xs);

        &:last-of-type {
            margin-right: 0;
        }
    }
}

Top

🔖 Выбор по тегам ×

💌 Написать сообщение ×

Все поля обязательны для заполнения!