Меньше абсолютного позиционирования с современным CSS

0 3

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

Вступление

Содержание статьи:

Если мы вернемся на 5 лет назад, CSS flexbox был все еще новым и не мог использовать надлежащих отступов. CSS-grid тогда даже не поддерживалась. В конце концов, мы использовали позиционирование CSS для достижения желаемого макета. Однако в наши дни некоторые из этих вариантов использования можно решить с помощью CSS flexbox или grid.
На днях мы работали над фронтендом целевой страницы, и мой партнер спросил меня о проблеме с макетом, с которой он столкнулся. Проблема возникла из-за position:absolute, я попытался помочь, и мы исправили эту проблему, даже не используя позиционирование CSS.

Случаи использования с примерами

Наложение в карточке

Когда у нас есть карточка, содержащая текст поверх изображения, мы часто используем position:absolute для размещения содержимого поверх изображения. В CSS-сетке это больше не требуется.

Меньше абсолютного позиционирования с современным CSS

Меньше абсолютного позиционирования с современным CSS

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Это типичная карточка с текстом поверх изображения. Вот HTML:

<article class=”card”> <div class=”card__thumb”> <img src=”assets/mini-cheesecake.jpg” alt=””> </div> <div class=”card__content”> <h2><a href=”#”>Title</a></h2> <p>Subtitle</p> </div> </article>

123456789 <article class=”card”>    <div class=”card__thumb”>        <img src=”assets/mini-cheesecake.jpg” alt=””>    </div>    <div class=”card__content”>        <h2><a href=”#”>Title</a></h2>        <p>Subtitle</p>    </div></article>

Чтобы разместить контент поверх изображения, нам нужно позиционировать .card__content абсолютно.

CSS .card { position: relative; } .card__content { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: linear-gradient(to top, #000, rgba(0, 0, 0, 0) bottom/100% 60% no-repeat; padding: 1rem; }

12345678910111213 .card {    position: relative;} .card__content {    position: absolute;    left: 0;    top: 0;    width: 100%;    height: 100%;    background: linear-gradient(to top, #000, rgba(0, 0, 0, 0) bottom/100% 60% no-repeat;    padding: 1rem;}

В приведенном выше примере нет ничего плохого, но почему бы не использовать более простое решение? Давайте исследуем это.

Первым делом нужно добавить display:grid в компонент карты. Нам не нужно устанавливать какие-либо столбцы или строки.

CSS .card { position: relative; display: grid; } .card__content { display: flex; flex-direction: column; justify-content: flex-end; }

12345678910 .card {    position: relative;    display: grid;} .card__content {    display: flex;    flex-direction: column;    justify-content: flex-end;}

Меньше абсолютного позиционирования с современным CSS

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

CSS .card__thumb, .card__content { grid-column: 1/2; grid-row: 1/2; }

12345 .card__thumb,.card__content {    grid-column: 1/2;    grid-row: 1/2;}

Более того, мы можем использовать сокращение grid-area:

CSS .card__thumb, .card__content { grid-area: 1/2; }

1234 .card__thumb,.card__content {    grid-area: 1/2;}

Меньше абсолютного позиционирования с современным CSS

Наконец, мы также можем использовать grid-area: 1/-1. -1 представляет собой последний столбец и строку в сетке.

Card Tag

Основываясь на предыдущем примере, мы хотим расширить его и включить тег в левую верхнюю часть карты. Для этого нам нужно использовать ту же технику grid-area: 1/-1, но мы не хотим, чтобы тег заполнял всю карту, верно?

Меньше абсолютного позиционирования с современным CSS

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

CSS .card__tag { align-self: start; justify-self: start; /* Other styles */ }

12345 .card__tag {    align-self: start;    justify-self: start;    /* Other styles */}

Познакомьтесь с тегом, который расположен над его родительским элементом, без использования position:absolute. Демо.

Herо-раздел

Еще один идеальный вариант использования — это hero-раздел с содержимым, перекрывающим изображение.

Меньше абсолютного позиционирования с современным CSS

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

Меньше абсолютного позиционирования с современным CSS

Есть разные способы реализовать это. Если изображение носит чисто декоративный характер, можно использовать background-image. В противном случае мы можем использовать элемент img.

CSS .hero { position: relative; min-height: 500px; } .hero__thumb { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; } /* The overlay */ .hero:after { content: “”; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #000; opacity: 0.5; } .hero__content { position: absolute; left: 50%; top: 50%; z-index: 1; transform: translate(-50%, -50%); text-align: center; }

12345678910111213141516171819202122232425262728293031323334 .hero {    position: relative;    min-height: 500px;} .hero__thumb {    position: absolute;    left: 0;    top: 0;    width: 100%;    height: 100%;    object-fit: cover;} /* The overlay */.hero:after {    content: “”;    position: absolute;    left: 0;    top: 0;    width: 100%;    height: 100%;    background-color: #000;    opacity: 0.5;} .hero__content {    position: absolute;    left: 50%;    top: 50%;    z-index: 1;    transform: translate(-50%, -50%);    text-align: center;}

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

Во-первых, нам нужно добавить display:grid к hero-элементу. После этого мы применим ту же концепцию, что и в компоненте карты grid-area:1/-1, к каждому прямому дочернему элементу.

Меньше абсолютного позиционирования с современным CSS

К сожалению, нам нужно будет использовать фиксированную высоту для hero-секции, чтобы сработало правило .hero__thumb. (Дочерний элемент с height:100% требует, чтобы его родительский элемент имел явную фиксацию height, а не min-height).

CSS .hero { display: grid; height: 500px; } .hero__content { z-index: 1; /* [1] */ grid-area: 1/-1; display: flex; flex-direction: column; margin: auto; /* [2] */ text-align: center; } .hero__thumb { grid-area: 1/-1; object-fit: cover; /* [3] */ width: 100%; height: 100%; min-height: 0; /* [4] */ } .hero:after { content: “”; background-color: #000; opacity: 0.5; grid-area: 1/-1; }

12345678910111213141516171819202122232425262728 .hero {    display: grid;    height: 500px;} .hero__content {    z-index: 1; /* [1] */    grid-area: 1/-1;    display: flex;    flex-direction: column;    margin: auto; /* [2] */    text-align: center;} .hero__thumb {    grid-area: 1/-1;    object-fit: cover; /* [3] */    width: 100%;    height: 100%;    min-height: 0; /* [4] */} .hero:after {    content: “”;    background-color: #000;    opacity: 0.5;    grid-area: 1/-1;}

Я хочу пройтись по пронумерованным строкам кода, поскольку они важны:

Мы можем использовать z-index сетки или flex элемента. Вообще не нужно добавлять position:relative.

Поскольку .hero__content это элемент сетки, использование margin:auto будет центрировать его по горизонтали и вертикали.

Не забывайте включать object-fit:cover при работе с изображениями.

Я использовал для hero-изображения min-height:0 в том случае, если использовалось большое изображение. Это сделано для того, чтобы заставить CSS-сетку учитывать height:100% и избегать увеличения размера изображения, больше чем hero-раздел, в случае, если автор использовал огромное изображение. Подробнее об этом вы можете прочитать в моей статье о минимальном размере содержимого в CSS-сетке.

Обратите внимание, как мы пришли к гораздо более чистому решению. Демо.

CSS display:contents

Я думаю, что это первый практический пример использования display:contents, который был для меня действительно полезный. Рассмотрим следующий пример, где у нас есть контент и изображение.

Меньше абсолютного позиционирования с современным CSS

<div class=”hero”> <div class=”hero__content”> <h2><!– Title –></h2> <p><!– Desc –></p> <a href=”#”>Order now</a> </div> <img src=”recipe.jpg” alt=””> </div>

12345678 <div class=”hero”>    <div class=”hero__content”>        <h2><!– Title –></h2>        <p><!– Desc –></p>        <a href=”#”>Order now</a>    </div>    <img src=”recipe.jpg” alt=””></div>

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

Меньше абсолютного позиционирования с современным CSS

Обратите внимание, что изображение теперь вставлено между заголовком и описанием. Как можно решить эту проблему? Поначалу может показаться, что разметка HTML должна быть изменена именно так.

<div class=”hero”> <div class=”hero__content”> <h2><!– Title –></h2> <img src=”recipe.jpg” alt=””> <p><!– Desc –></p> <a href=”#”>Order now</a> </div> </div>

12345678 <div class=”hero”>    <div class=”hero__content”>        <h2><!– Title –></h2>        <img src=”recipe.jpg” alt=””>        <p><!– Desc –></p>        <a href=”#”>Order now</a>    </div></div>

На мобильном телефоне все может работать как положено. На десктопе нам нужно расположить img с правой стороны. И хотя это работает, но есть более простое решение display:contents. Вернемся к исходной разметке.

<div class=”hero”> <div class=”hero__content”> <h2><!– Title –></h2> <p><!– Desc –></p> <a href=”#”>Order now</a> </div> <img src=”recipe.jpg” alt=””> </div>

12345678 <div class=”hero”>    <div class=”hero__content”>        <h2><!– Title –></h2>        <p><!– Desc –></p>        <a href=”#”>Order now</a>    </div>    <img src=”recipe.jpg” alt=””></div>

Обратите внимание, что содержимое завернуто внутрь .hero__content. Как мы можем сказать браузеру, что мы хотим, чтобы <h2>, <p> и <a> были наследниками того же родительского элемента, что и img? Что ж, с display:contents я могу это сделать:

Меньше абсолютного позиционирования с современным CSS

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

CSS .hero__content { display: contents; }

123 .hero__content {    display: contents;}

Браузер проанализирует разметку следующим образом.

<div class=”hero”> <h2><!– Title –></h2> <p><!– Desc –></p> <a href=”#”>Order now</a> <img src=”recipe.jpg” alt=””> </div>

123456 <div class=”hero”>    <h2><!– Title –></h2>    <p><!– Desc –></p>    <a href=”#”>Order now</a>    <img src=”recipe.jpg” alt=””></div>

Все, что нам нужно сделать в CSS, это следующее.

CSS .hero { display: flex; flex-direction: column; } .hero__content { display: contents; } .hero h2, .hero img { order: -1; }

12345678910111213 .hero {    display: flex;    flex-direction: column;} .hero__content {    display: contents;} .hero h2,.hero img {    order: -1;}

При правильном использовании display:contents — это мощный метод для достижения того, что было невозможно несколько лет назад. Конечно, мы также хотим заняться стилем для десктопа.

CSS @media (min-width: 750px) { .hero { flex-direction: row; } .hero__content { display: initial; } .hero h2, .hero img { order: initial; } }

1234567891011121314 @media (min-width: 750px) {    .hero {        flex-direction: row;    }        .hero__content {        display: initial;    }        .hero h2,    .hero img {        order: initial;    }}

Демо

Изменение порядка элементов компонентов карты

Меньше абсолютного позиционирования с современным CSS

В этом примере у нас есть вариант карты, в которой заголовок помещается вверху карты. Давайте посмотрим на разметку HTML.

<article class=”card”> <img src=”thumb.jpg” alt=””> <div class=”card__content”> <h3>Title</h3> <p>Description</p> <p>Actions</p> </div> </article>

12345678 <article class=”card”>    <img src=”thumb.jpg” alt=””>    <div class=”card__content”>        <h3>Title</h3>        <p>Description</p>        <p>Actions</p>    </div></article>

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

CSS .card { position: relative; padding-top: 3rem; /* Accommodate for the title space */ } .card h3 { position: absolute; left: 1rem; top: 1rem; }

1234567891011 .card {    position: relative;    padding-top: 3rem;    /* Accommodate for the title space */} .card h3 {    position: absolute;    left: 1rem;    top: 1rem;}

Однако это решение может не сработать, если заголовок слишком длинный.

Меньше абсолютного позиционирования с современным CSS

Это происходит потому, что заголовок выходит за рамки обычного потока, поэтому браузер фактически не заботится о том, насколько он короткий или длинный. Мы можем найти гораздо лучшее решение используя display:contents:

CSS .card { display: flex; flex-direction: column; padding: 1rem; } .card__content { display: contents; } .card h3 { order: -1; }

12345678910111213 .card {    display: flex;    flex-direction: column;    padding: 1rem;} .card__content {    display: contents;} .card h3 {    order: -1;}

Это позволит нам контролировать все дочерние элементы и иметь возможность записывать их по мере необходимости с помощью свойства order.

Меньше абсолютного позиционирования с современным CSS

У нас все еще есть небольшая проблема, так как мы добавили padding:1 rem родительскому элементу. Изображение должно быть приклеено к краям. Вот как мы можем это исправить:

CSS .card img { width: calc(100% + 2rem); margin-left: -1rem; }

1234 .card img {    width: calc(100% + 2rem);    margin-left: -1rem;}

Центрирование

Когда дело доходит до центрирования, вы увидите множество шуток о том, как это сложно. В наши дни центрировать элемент намного проще, чем когда-либо.

Больше не нужно использовать преобразования position:absolute. Например, мы можем использовать margin:auto для центрирования гибкого элемента как по горизонтали, так и по вертикали.

CSS .card { display: flex; } .card__image { margin: auto; }

1234567 .card {    display: flex;} .card__image {    margin: auto;}

Меньше абсолютного позиционирования с современным CSS

Соотношение сторон изображения

Новое свойство CSS aspect-ratio теперь поддерживается во всех основных браузерах. Раньше мы использовали отступы, чтобы соблюдать определенное соотношение сторон.

CSS .card__thumb { position: relative; padding-top: 75%; } .card__thumb img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; }

12345678910111213 .card__thumb {  position: relative;  padding-top: 75%;} .card__thumb img {  position: absolute;  left: 0;  top: 0;  width: 100%;  height: 100%;  object-fit: cover;}

С новым aspect-ratio это намного проще.

CSS /* */ .card__thumb { position: relative; aspect-ratio: 4/3; }

12345 /*  */.card__thumb {  position: relative;  aspect-ratio: 4/3;}

Иногда лучше использовать рosition:аbsolute

Меньше абсолютного позиционирования с современным CSS

В этом примере у нас есть контент (аватар, имя и ссылка), перекрывающий обложку карты. У нас есть два варианта реализации этого:

Использовать position:absolute для обложки карты

Использовать отрицательное поле для содержимого

Давайте рассмотрим решения и посмотрим, какое из них больше подходит для этого варианта использования.

Использование абсолютного позиционирования

Меньше абсолютного позиционирования с современным CSS

С помощью этого решения мы можем позиционировать прямоугольник абсолютно, а затем добавить padding:1rem к содержимому карты.

CSS .card__cover { position: absolute; left: 0; top: 0; width: 100%; height: 50px; } .card__content { padding: 1rem; }

1234567891011 .card__cover {    position: absolute;    left: 0;    top: 0;    width: 100%;    height: 50px;} .card__content {    padding: 1rem;}

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

Меньше абсолютного позиционирования с современным CSS

Использование отрицательных полей

В этом решении карта не будет позиционироваться абсолютно. Вместо этого контент будет иметь отрицательное поле сверху.

CSS .card__content { padding: 1rem; margin-top: -1rem; }

1234 .card__content {    padding: 1rem;    margin-top: -1rem;}

Хотя это решение работает при наличии покрытия карты, оно может вызвать проблемы, когда у нас есть вариант карты без покрытия.

Меньше абсолютного позиционирования с современным CSS

Обратите внимание, как аватар находится за пределами своего родителя (карты). Чтобы исправить это, нам нужно изменить CSS и удалить отрицательное поле.

CSS .card–no-cover .card__content { margin-top: 0; }

123 .card–no-cover .card__content {    margin-top: 0;}

В результате — использование position:absolute оказалось лучшим решением, так как избавит нас от написания дополнительных CSS. Надеюсь, вам понравилась статья. Спасибо за чтение!

Автор: Ahmad Shadeed

Источник: webformyself.com

Оставьте ответ