Все должно быть изложено так просто, как только возможно, но не проще.
А. Эйнштейн

Добрый день уважаемые разработчики. Довольно часто просматривая копаясь в чужом коде я наталкиваюсь на такое написание кода для кнопки с иконкой.

HTML

<div class="bl_button__wrapp">
  <div class="bl_button">
      <i class="fa fa-bars" aria-hidden="true"></i>
      <span class="bl_button__text">menu</span>
    </div>
</div>

CSS

.bl_button__wrapp{
  width: 100%;
  margin: 5% auto;
  font-size: 30px;
  line-height: 34px;
  color: blue
}
.bl_button{
  position: relative;
  width: 150px;
  padding: 10px;
  margin: 0 auto;
  text-align: center;
  border: 1px solid #00f;
  cursor:pointer;
}

.fa-bars{
  position: absolute;
  left: 10px;
  font-size: 34px;
}
.bl_button__text{
  display: inline-block;
}


See the Pen bad button by Andry Zirka (@BlackStar1991) on CodePen.

Это стандартная форма описания кнопки. Я сам долгое время примерно так писал свой код. Данное написание особо практикуется теми, кто использует готовые иконочные шрифты на подобии FontAwesome
Небольшие трудности возникают если текст должен быть по центру, а иконка несколько смещена относительно текста. Но всё это прекрасно решаемо через свойство position:absolute; задаваемое иконке. Также бывают проблемы с позиционированием данной иконки при адаптивности кнопки, но это другая история.

Теперь я хотел бы описать свой метод оформления иконок в тексте страници (на примере всё того же FontAwesome).

HTML

<button class="button_menu">
  <span class="button_menu__text button_icon__menu">menu</span>
</button>

<button class="button_menu">
  <span class="button_menu__text button_icon__menu">Съешь ещё этих мягких французских булок.</span>
</button>

CSS

.button_menu{
  
  min-width: 280px;
  margin-top: 5%;
  margin-left: 4%;

  font-size: 4em;
  color: blue;
  border: 1px solid #00f;
  
  outline:none; /* Убираем если вас это смущает по дизайну*/
  background:none;  /* Убираем если вас это смущает по дизайну*/
}

.button_menu__text{
  position:relative;
  width: 100%;
  display: inline-block;
  text-align: center;
  margin: 0 auto;
  padding: 10px 40px; 
}
.button_icon__menu:before{
  content: "\f0c9";
  font-family: FontAwesome;
  position: absolute;
  left: 0px;
  top: 14px;
}

See the Pen good button by Andry Zirka (@BlackStar1991) on CodePen.



Преимущества такого описания.

1) Кода стало меньше. (Это существенно облегчит вам жизнь на масштабных проектах).

2) Код стал семантически более верным. Если div(или любой другой тег) функционально у Вас выполняет назначение кнопки, то и делайте его через тег button *Иначе возможны проблемы, особенно с Apple устройствами для которых придется прописывать type=«button» для вашего не правильного тега.

3) span размещенный внутри button всегда выравнивается по центру. (*Можно сменить ему display: если вам важны внутренне отступы).

4) Как вы могли заметить, вся суть моего оформления в том что я выношу изображение иконки через псевдо класс :before (:after) и позиционирую его абсолютно. При этом у его родителя span установлен position:relative; (! Важно, чтобы для иконки присваивался отдельный класс).

5) Иконка будет всегда на своем месте относительно span, даже если у вас предусмотрена смена языка, и скажем, в другом языке данное слово могло бы визуально перекрыть иконку.

6) Иконки, оформленные таким образом легко менять, особенно если вы используете препроцессоры (SASS, SCSS, LESS...), просто добавь нужный класс к нужному элементу.

Недостатки такого описания: (а куда же без них).

1) При использовании тега button довольно часто приходится сбрасывать или переопределять стили, иначе выглядит не очень.

outline:none; 
 background:none; 
 border:none; 

2) Для каждого родительского (span) допустимо одновременно отображать только две иконки, собственно на псевдокласс :before и :after.

3) Если вы, как и я, довольно часто в своих работах используете FontAwesome, вам чаще придется посещать их официальный сайт, что бы выучить Unicode каждой иконки



Это несколько сложнее чем просто прописать классы fa fa-bars. Здесь есть и полный список иконок

4) Поскольку я в написании своего CSS стараюсь придерживаться методологии, то у меня для родительского элемента может быть и довольно много классов

<button class="button_menu">
  <span class="button_menu__text button_icon button_icon__menu button_icon__menu_active">menu</span>
</button>

Но если вас не пугает 4-5 классов для элемента, тогда Welcome.

Комментарии (23)


  1. Finesse
    14.08.2017 17:55
    +5

    Никак не пойму, зачем 2 элемента. Почему бы не сделать так https://codepen.io/anon/pen/RZLjKZ?


    1. walovari
      14.08.2017 18:50

      Потому что кнопка может быть и без иконки


      1. KYuri
        14.08.2017 20:28

        И что? Finesse очень хороший пример привел.
        Расширяемый: https://codepen.io/anon/pen/wqrmKy


    1. Zvezdocheteg
      15.08.2017 07:57

      2 элемента, как по мне хороший вариант, только вторым элементом, нужно не оборачивать текст, а делать его для иконки.
      Почему иконку делать отдельным элементом, чтобы можно было манипулировать ей с javascript и в html структура верстки чище.

      <button class="button">
        <i class="button__icon"></i>menu
      </button>
      


      1. BlackStar1991 Автор
        15.08.2017 08:00

        Да, такой вариант тоже смотрится прилично, при условии что иконка присвоена именно к кнопке (по дизайну), а не к ссылке или параграфу


        1. Zvezdocheteg
          15.08.2017 12:19

          Без разницы. Я беру пример с вашей статьи, в ней логический элемент это button, то что внутри контент(текст) и иконка (декор).
          Меньше html не значит лучше, структуру должна быть разбита на логические кусочки с которыми можно работать и легко читать и поддерживать.

          Вот к примеру, из описанных вами недостатков.пример:

          <button class="button_menu">
            <span class="button_menu__text button_icon button_icon__menu button_icon__menu_active">menu</span>
          </button>
          


          Как то совсем не по методологии, у вас тег span является элементом к .button_menu и .button, если же иконка является декорирующим элементом к тексту, то соответственно вместо классов (button_icon, button_icon__menu, button_icon__menu_active), добавляем к элементу button_menu__text модификатор к примеру button-menu__text--icon-menu

          Проще же так:
          <button class="button-menu button-menu--active">
              <i class="button-menu__icon button-menu__icon--menu"></i>
              <span class="button-menu__text">menu</span>
          </button>
          


  1. barkalov
    14.08.2017 17:56
    +5

    Иконка с position: absolute, а текст position: relative? Браво.


    1. u4ria
      14.08.2017 18:15
      +5

      А еще можно так.
      image


      1. u4ria
        14.08.2017 18:27

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


        1. BlackStar1991 Автор
          14.08.2017 21:07

          Замечание принимается, спасибо. Уже поправил


  1. webdevium
    14.08.2017 18:50

    Та можно «дезоксирибонуклеиновая кислота» вписать в кнопку и все поплывет.
    Все же зависит от контекста, в котором эта кнопка будет использоваться.


  1. Firefoxic
    14.08.2017 21:53
    +1

    Вторая половина 2017… они всё ещё используют иконочные шрифты.
    Уже даже гитхаб от этой фигни отказался давно.


    1. pda0
      15.08.2017 00:12

      Хм… А почему, кстати? Я просто пристально за вебом не слежу.


      1. spmbt
        15.08.2017 01:50
        +1

        Первое, что нашёл с кучей доводов: https://dev.atom-m.net/stat/seryozno_ne_ispolzuite_ikonochnye_shrifty.htm

        Не хватает ещё довода «не семантично». Но семантичность никак не связана с табличной вёрсткой, как там упомянуто в конце. В 2 словах — шрифты — не инструмент для картинок, поэтому семантику картинок трудно подвешивать к ним.


    1. psFitz
      15.08.2017 10:16

      Плюсик, проще добавить инлайн свг в один файлик, а дальше по id дергать, лучше функцией типа
      <?= get_icon('menu'); ?>


  1. XAHTEP26
    14.08.2017 22:20
    -1

    Насчет того что надо использовать button — согласен. А насчет остального нет.
    Посмотрите как сделаны кнопки «Fork», «Settings», «Change view» на том же CodePen, где вы писали примеры. Для меня этот вариант наиболее верный.


  1. neurocore
    15.08.2017 08:26

    Что-то конструктивной критики иконочных шрифтов я не заметил.
    Плюсы:

    • из коробки
    • простая вёрстка

    Минусы были предложены:
    • проблемы в читалках — уж очень частный случай
    • семантика картинок — иконка есть иконка, что ещё к ней хотите прицепить?
    • дислексия??

    Реальные минусы:
    • нет масштабируемости по умолчанию


    1. Aingis
      15.08.2017 11:15

      Проблемы с поддержкой (читалки, Опера мини, заменённый шрифт и т.п.), субпиксельным рендерингом (у SVG тоже бывают в некоторых особых случаях, но они хоть решаемы), позиционированием (выровняйте по вертикальному центру, ага), раскрашиванием (одна иконка — один цвет и всё), и т.д. Не будте предвзяты.


  1. Jokerjar
    15.08.2017 08:42

    По ссылке выше не ходил, но, считаю, парой самых веских минусов шрифтовых иконок — их монохромность и «увесистость» (как правило, подобные паки содержат большое кол-во символов, далеко не все используются на сайте).


    1. KYuri
      15.08.2017 08:54
      +1

      Так необязательно всю кучу тащить — можно выбирать только то, что используется.
      Гляньте, например, http://fontello.com/


  1. psFitz
    15.08.2017 10:29

    del


  1. psFitz
    15.08.2017 10:40

    Вообще в статье какие-то костыли описаны, если используются шрифты, почему не сделать все одним элементом? зачем такое огромное количество css кода? position: absolute в кнопке вообще топчик, а если высота кнопки изменится будете менять позицию всех иконок вручную? Отличный пример как не надо делать