Технологии веб-разработки основаны на простых принципах, которые зачастую сложно понять. С этим, пожалуй, сталкиваются все начинающие программисты. Один из подходов к пониманию технологий, а значит – к их эффективному применению, заключается во взгляде на них через аналогии из реального мира.

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

Итак, вы оказались в автосалоне, в котором выставлены машины разных марок, цветов, выпущенные в разное время. В таких местах обычно встречаются и продавцы, но их мы в наш пример включать не будем.

Автомобили, а также их характеристики, можно классифицировать, используя ту же систему, которая лежит в основе CSS-селекторов. И если вам понятно, что автомобили на рисунке ниже можно разделить на седаны, кабриолеты и лёгкие грузовики, это значит, что вы сможете понять и то, как устроены CSS-селекторы.



Для начала опишем автомобили, выставленные на продажу, с помощью HTML-кода:

<section>
    <div class='sedan blue 2015 leatherSeats'></div>
    <div class='sedan red 2012 hatchback'></div>
    /** 10 more */
</section>
<section>
    <div id="123xyz" class='convertible purple audi v8'></div>
    <div class='convertible green mustang dualExhaust'></div>
    /** 10 more */
</section>
<section>
    <div id="789abc" class='truck 2014 seatWarmer crewCab'></div>
    <div class='truck 2013 powerSteering'></div>
    /** 10 more */
</section>

Мы собираемся рассмотреть четыре базовых способа стилизации HTML-элементов с помощью CSS. А именно:

  1. По типу элемента. В нашем случае речь идёт о теге <div>, содержащем сведения об автомобиле.
  2. По классу (class). Например, это класс blue, назначенный первому автомобилю в коде.
  3. По идентификатору (id). Пример идентификатора из кода – 123xyz.
  4. По отношениям с другими элементами

Рассмотрим эти варианты подробнее.

Типы элементов


В вышеприведённом примере HTML-кода каждый тег <div> символизирует отдельный автомобиль. Предположим, нам нужно, с использованием CSS, назначить некие свойства всем этим автомобилям. Что у них общего у седанов (sedan), кабриолетов (convertible) или лёгких грузовиков (truck)? На самом деле, список может получиться очень длинным, но мы ограничимся тремя свойствами. У каждого из наших автомобилей по четыре колеса, максимальная высота автомобиля не превышает 270 сантиметров, а кузов каждого сделан из стали. Запишем эти рассуждения в следующем виде:

div{
    wheels: 4;
    max-height: 270;
    material: steel;
}

С этого простого примера мы и начнём. Как видите, здесь задействованы некоторые CSS-свойства, которые будут по умолчанию применяться к тегам <div>. Как к тем, которые уже в коде есть, так и к тем, которые мы можем к нему добавить позже. Обратит внимание на то, что этот код уместно будет назвать «псевдо-CSS», так как при стилизации, скажем, тех же тегов <div> на реальной веб-странице, в дело пойдут совсем другие свойства.

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

<div class='sedan'>
    <div class='frontRow'>
        <div class='window'></div>
        <div class='seat'></div>
        <div class='seat'></div>
        <div class='window'></div>
    </div>
    <div class='backRow'>
        <div class='window'></div>
        <div class='seat'></div>
        <div class='seat'></div>
        <div class='seat'></div>
        <div class='window'></div>
    </div>
</div>

Седаны имеют два ряда сидений. Передний ряд (frontRow) содержит два кресла, задний (backRow) – три. Крайние кресла в рядах находятся около окон. Есть ли у сидений автомобилей какие-нибудь общие свойства? Выясним это чуть позже.

Классы


Взгляните на самый первый фрагмент HTML-кода, который содержит описание всех автомобилей, выставленных на продажу. Обратите внимание на то, что каждому тегу <div>, символизирующему автомобиль, назначен набор классов. Эти классы используются для придания общих свойств всем членам класса.

Скажем, мы назначаем класс year2005 различным седанам, грузовикам и кабриолетам, вышедшим с конвейера в 2005-м году. Что общего может быть у таких автомобилей? Например – автомагнитола с CD-плеером! Отразим это в CSS-коде, который задаёт стиль класса.

.year2005{
    muiscPlayer: cd;
}

А что если у нас имеется класс crewCab, символизирующий наличие у автомобиля, в частности, у грузовика, двойной кабины? У грузовиков с такой кабиной имеется два ряда сидений, в которых, в общей сложности, оказывается пять кресел. Этот класс можно использовать специально для грузовиков. Классы комбинируют, записывая их друг за другом через точку:

.truck.crewCab{
    seats: 5;
}

Классы – это более конкретный, чем тип элемента, способ ссылаться на HTML-элементы. Например, основной материал кузовов всех автомобилей по умолчанию – сталь. Но нужно отразить то, что некоторые авто имеют алюминиевый кузов. Для этого можно создать класс aluminium, который, будучи применён к тегу <div>, переопределит свойство material у всех членов класса. Вспомним: выше мы установили свойство material для всех элементов <div> в значение steel.

div{
    material: steel;
}

Теперь, применив класс aluminium к некоторым из элементов <div>, мы изменим steel на aluminium.

.aluminum{
    material: aluminum;
}

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

Идентификаторы


HTML-элементам можно назначать идентификаторы, которые должны быть уникальными для каждого элемента. Это – самый точный способ обращения к отдельному элементу. Стиль, назначенный идентификатору, переопределяет все остальные стили. Идентификатор элемента очень похож на номерной знак автомобиля.



Скажем, у нас имеется автомобиль с номером 123 XYZ. Предыдущий владелец захотел, чтобы этот автомобиль покрасили в неповторимый оттенок фиолетового цвета. Вот описание этого факта в CSS:

#123xyz{
    color: weirdpurple;
}

Элемент и его идентификатор соотносятся как «один-к-одному». Это очень напоминает реальные автомобили и их номерные знаки. У двух машин не может быть одинаковых номеров. Идентификатор, кроме того, самый мощный способ адресации элемента, благодаря которому можно создавать исключения из правил, которым должны подчиняться все элементы.

Взаимоотношения между элементами


Предположим, нам нужно, чтобы автомобили, которым назначен класс leatherSeats имели кожаные сиденья. Взгляните на второй фрагмент HTML-кода из раздела «Типы элементов», в котором мы описывали оформление салонов автомобилей.


Для того, чтобы достичь желаемого эффекта, можно, для автомобилей с кожаными сиденьями, назначить каждому тегу <div> с классом seat ещё и класс leather. Но вот в чём дело: такой подход позволит нам обращаться лишь к сиденьям, воздействовать с помощью CSS только на «кожаные сиденья», а не на «автомобили с кожаными сиденьями». Ведь в теге <div>, соответствующем всему автомобилю, упоминаний о сиденьях нет.

Теги с классом seat расположены внутри тегов с классами sedan, convertible или truck. Это значит, что «сиденья» в нашем примере являются потомками «автомобилей». Поэтому, для того, чтобы у нас была возможность обращаться и к «автомобилю с кожаными сиденьями», и к самим «сиденьям», назначим класс leatherSeats автомобилям с кожаными сиденьями, а для обращения к сиденьями используем такую конструкцию:

.leatherSeats .seat{
    material: leather;
}

Обратите внимание на то, что имена классов разделены пробелом. Это – так называемый селектор потомков. В результате, CSS-код из примера позволяет стилизовать все элементы с классом seat, которые находятся в контейнере, которому назначен класс leatherSeats.

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

Например, это может выглядеть так:

.driverSeat ~ .seat{
    seatWarmers: true;
}

И вот ещё пример. Скажем, некая модель автомобиля отличается весьма необычными свойствами. Например, лёгкий грузовик Chevrolet 2008-го года оснащён DVD-плеерами, встроенными в задние сиденья. Вот какие рассуждения помогут выразить это в виде CSS:

  1. Начать нужно с нескольких классов, так как речь идёт о весьма специфическом типе автомобиля. Например, это может быть div.truck.chevy.year2008.

  2. Затем стоит подумать о том, как можно обратиться к задним сиденьям. Заднему ряду сидений можно назначить дополнительный класс. Скажем, что-то вроде .backRow. Или можно воспользоваться селектором last-child, позволяющий выбрать последнего потомка, учитывая то, что в описании салона автомобиля сначала идут передние сиденья, потом – задние.

  3. И, наконец, нужно обратиться к самим сиденьям.

В итоге выглядеть это может так:

div.chevy.truck.year2008 .backRow .seat{
    media: dvdPlayer;
}

Итоги


Если вы плохо представляли себе особенности работы с CSS, надеюсь, этот пример помог вам понять то, что раньше было неясно. Его главное предназначение заключается в том, чтобы, перейдя от абстрактных понятий HTML и CSS, ко вполне осязаемым, конкретным автомобилям, помочь вам представить то, как CSS-стили влияют на HTML-документы. И, если вам удалось уложить в голове то, о чём мы говорили, открывайте редактор, да хотя бы тот же codepen.io, берите справочники по HTML и CSS, и приступайте к собственным экспериментам с кодом, которые позволят закрепить на практике всё то, что вы узнали и поняли.
Поделиться с друзьями
-->

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


  1. vlreshet
    12.12.2016 16:51
    +6

    Вот бы сейчас в 2016 году основы CSS рассказывать.


  1. Doomsday_nxt
    12.12.2016 17:39
    +1

    Я вот понимаю как работают CSS-селекторы… Но чем дальше читал пост, тем больше не понимал — что происходит…


    1. Mr_Edward
      12.12.2016 18:27
      +1

      Полагаю, метод хранения данных об автомобилях в CSS.


      1. Doomsday_nxt
        12.12.2016 19:03
        +2

        Ну это конечно что-то новенькое… СУБД-CSS :-)


        1. koeshiro
          13.12.2016 16:49

          Идея интересная. Пытался реализовать на втором курсе. Но… дело скучное и не очень удобное. Получается что-то вроде не структурированного json-а. В котором приходится пробегаться по всем строкам что бы найти все совпадения.


  1. WebMonet
    12.12.2016 20:17
    +1

    Очень хотел увидеть иллюстрацию специфичности на примере автосалона, но…


  1. webirus
    13.12.2016 00:07
    +1

    Я думал, что просто чего-то не понимаю, но почитав комментарии, убедил, что я не один такой. Невнятная статья какая-то.


    1. itforge
      13.12.2016 05:11

      Я даже под кат не стал заглядывать, офигел от картинки с седанами и грузовиками и сразу в комменты пошёл :)


  1. phoenixweiss
    13.12.2016 08:11
    +2

    Вы умудрились рассказать на чертовски неудачных примерах то что все посетители хабра и так знают, а новички попросту не поймут из-за чрезмерно абстрактной аналогии. Это как рассказывать о приготовлении омлета через теорию Броуновского движения частиц.

    И тем не менее, пост попадает в закладки как пример того как иногда не нужно использовать построения аналогий для объяснения относительно простых вещей.


  1. seokirill
    13.12.2016 08:13

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


  1. starowere
    13.12.2016 11:38
    +1

    К тому же допущена серьезная ошибка — CSS не понимает селекторов id и class, начинающихся с цифр. Этот код не будет работать:

    #123xyz{
    color: weirdpurple;
    }


    1. zhigalin
      18.12.2016 17:18

      Можно подумать что другие примеры кода здесь рабочие…