Задачка про страницу в три столбца, один из них в сто пикселей

в 10:26, , рубрики: css, html, web-разработка, верстка, лабораторные работы, оформление кода

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

Разработать страницу, состоящую из трех разноцветных столбцов. Левый столбец шириной 100 пикселей, центральный и правый занимают все оставшееся до края страницы место равномерно. Высота всех трех 100% страницы. Не должно быть скроллбара и белых полос вокруг страницы.

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

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

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

I вариант

Первый вариант — совсем студенческий. Обычно подобным образом все и выглядело. И по понятным причинам: студент, имея в качестве бэкграунда только понимание общего принципа работы связки технологий HTML+CSS и самых простых CSS-селекторов, наверно, ничего другого и не мог написать.

<body>
  <div class="one"></div>
  <div class="two"></div>
  <div class="three"></div>
</body>

body {
  display: flex;
}
.one {
  width: 100px;
  height: 100%;
  background: red;
}
.two {
  width: calc(50vw - 50px);
  height: 100%;
  background: green;
}
.three {
  width: calc(50vw - 50px);
  height: 100%;
  background: blue;
}

CODEPEN

При чем надо понимать, что некоторые юные программисты слыхом не слыхивали о правилах оформления кода, поэтому его «красота» и читабельность требовали рефакторинга.

Итак, здесь мы имеем несколько антипаттернов: незначащие имена классов, многократное повторение кода, а также отсутствие контейнера и, как следствие, стилизация body. На этом этапе студенты погружались в изучение соглашения по именованию в БЭМ и приципов DRY, DIE, KISS, SOLID, YAGNI.

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

body {
  max-width: 1024px;
}

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

Далее для краткости вынесем общие повторяющиеся стили. Здесь содержимое растягивается на всю страницу и определяются цвета для заливки столбцов. Эти стили будут использоваться во всех последующих примерах.

html, body {
  height: 100%;
  margin: 0;
}
.red {
  background: red;
}
.green {
  background: green;
}
.blue {
  background: blue;
}

II вариант

Другим самым очевидным оказался вариант раскладки в таблицу. Сыграло свою роль ключевое слово «столбец» в постановке задачи.

<table class="blocks">
  <td class="blocks--block__fixed-width red"></td>
  <td class="blocks--block green"></td>
  <td class="blocks--block blue"></td>
</table>

.blocks {
  height: 100%;
  border-collapse: collapse;
}
.blocks--block__fixed-width {
  width: 100px;
}
.blocks--block {
  width: calc(50vw - 50px);
}

CODEPEN

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

III вариант

Особенностью следующего варианта является дополнительная обертка для второго и третьего столбца. Эта обертка (wrapper) позволяет проще решать задачу распределения пространства страницы между центральным и правым стобцами без использования возможностей Flexbox Layout.

<div class="blocks">
  <div class="blocks--block__fixed-width red"></div>
  <div class="blocks--wrapper">
    <div class="blocks--block green"></div>
    <div class="blocks--block blue"></div>
  </div>
</div>

.blocks, .blocks--wrapper {
  display: flex;
  height: 100%;
}
.blocks--wrapper {
  width: calc(100% - 100px);
}
.blocks--block {
  width: 50%;
}
.blocks--block__fixed-width {
  width: 100px;
}

CODEPEN

IV вариант

В следующем примере, во-первых, используются псевдоклассы :first-child и :not(:first-child) для выделения соответственно первого и всех_кроме_первого элементов, имеющих class="block". Во-вторых, используется больше возможостей Flexbox Layout, в частности свойство дочерних элементов flex, которое объединяет свойства flex-grow, flex-shrink и flex-basis и, таким образом, определяет относительные размеры элементов.

<div class="blocks">
  <div class="block red"></div>
  <div class="block green"></div>
  <div class="block blue"></div>
</div>

.blocks {
  display: flex;
  height: 100%;
}
.block:first-child {
  flex: 0 0 100px;
}
.block:not(:first-child) {
  flex: 1 1 auto;
}

CODEPEN

Большим преимуществом предыдущего варианта считаю однократное вхождение зависимости от ширины левой колонки. Это в значительной мере облегчает поддержку и дальнейшую разработку проекта.
Следующий момент, который хочется подчеркнуть отдельно: если количество отднотипных колонок будет увеличиваться и будет принято решение воспользоваться, например, функцией map для их создания, то подобный метод стилизации позволит это осуществить гораздо проще. Рассмотрим этот случай на примере следующего кода:

<div id="root"></div>

const colours = ['red','blue','green'];

const blocks = colours.map(colour => 
      <div className={"block " + colour}></div>
    );

ReactDOM.render(
  <div className="blocks">{blocks}</div>,
  document.getElementById('root')
);

#root, html, body {
  height: 100%;
  margin: 0;
}
.blocks {
  display: flex;
  height: 100%;
  width: 100%;
}
.block:first-child {
  flex: 0 0 100px;
}
.block:not(:first-child) {
  flex: 1 1 auto;
}

CODEPEN

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

V вариант

И последний вариант решения поставленной задачи, только с оговоркой, что она состоит именно в раскрашивании страницы.

<div class="container"></div>

html, body {
  height: 100%;
  margin: 0;
}
.container {
  width: 100%;
  height: 100%;
    background: linear-gradient(
    to right, 
    red 100px, 
    green 100px,
    green calc(50% + 50px),
    blue calc(50% + 50px)
  );
}

CODEPEN

Здесь используется свойство background, которое задает градиентное изменение цветов слева на право. Для чёткой границы каждый последующий цвет начинается с точки остановки предыдущего цвета.

Автор: ErisNuts

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js