Критерии
Вот рабочее решение, которое мне удалось придумать (измените размер контейнера, чтобы увидеть, как он ведет себя при разных соотношениях сторон)
.grid {
resize: both;
width: 100px;
height: 200px;
border: 3px solid black;
overflow: hidden;
display: flex;
flex-wrap: wrap;
}
.cell {
display: flex;
box-sizing: border-box;
height: 25%;
width: 50%;
position: relative;
}
.inner {
flex: 1;
box-sizing: border-box;
margin: auto;
aspect-ratio: 1/1;
max-height: 100%;
}
.content {
box-sizing: border-box;
border: 3px solid blue;
background-color: #8080ff;
aspect-ratio: 1/1;
max-height: 100%;
margin: auto;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class = "grid">
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
<div class = "cell">
<div class = "inner">
<div class = "content"></div>
</div>
</div>
</div>
</body>
</html>
Мое текущее решение функционально, но у меня есть несколько проблем с ним:
display: grid;
Я пытаюсь изучить макет display: grid;, и это кажется проблемой, когда очевидным выбором будет сетка, но я еще не нашел решения, которое ее использует.
Решение, которое я предоставил, является эталонной реализацией того, как оно должно работать. Я ищу реализацию с таким же поведением, но с использованием display: grid;.
Вот моя попытка использовать сетку:
.grid {
border: 3px solid black;
resize: both;
overflow: hidden;
width: 100px;
height: 200px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.cell {
box-sizing: border-box;
border: 2px solid red;
background-color: rgb(255, 161, 161);
max-height: 100%;
overflow: hidden;
}
.content {
margin: auto;
box-sizing: border-box;
border: 5px solid blue;
background-color: rgb(136, 136, 255);
aspect-ratio: 1/1;
max-height: 100%;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class = "wrap">
<div class = "grid">
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
<div class = "cell">
<div class = "content"></div>
</div>
</div>
</div>
</body>
</html>
Как видите, мое решение сетки не удовлетворяет всем критериям. Ячейки не выровнены по вертикали в своей строке. Обычные способы вертикального выравнивания div ломали макет.
Возможно ли это даже с чистым макетом сетки CSS или использование flex/table/что-либо неизбежно?
@Pete Это именно то, что я хочу, но с точки зрения качества кода у меня есть проблемы с ним.
Если вы хотите создать сетку, рекомендуется использовать display:grid… Как вы говорите, это уменьшит количество оберток и упростит ваш код. Я не уверен, в чем именно проблема? Вы пробовали использовать сетку?
@Kokodoko Если бы я не пытался использовать сетку, мне не пришлось бы делать этот пост, проблема с сеткой заключалась в том, что либо ячейки не сохраняли соотношение сторон, либо ячейки переполняли контейнер, либо ячейки были выровнен по вертикали сверху, а не посередине
Что касается упрощения кода, вы можете начать с удаления <div class = "grid">. Если я правильно понимаю, вы можете добавить display: flex; flex-wrap: wrap; к классу wrap, и поведение будет таким же.
@IvanBeliakov Спасибо за отзыв! В реальном проекте у этой оболочки есть функция. Но в моем минимально воспроизводимом примере он теряет свою функцию и, следовательно, не нужен. Спасибо, что указали на это, я удалил это из поста.
@Kokodoko Я добавил свою попытку сетки в пост
Согласно документации по гибкому контейнеру MDN:
align-items: center;
justify-content: center;
Может центрироваться по вертикали
.grid {
border: 3px solid black;
resize: both;
overflow: hidden;
width: 100px;
height: 200px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.cell {
box-sizing: border-box;
border: 5px solid red;
background-color: rgb(255, 161, 161);
max-height: 100%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class = "wrap">
<div class = "grid">
<div class = "cell">
1
</div>
<div class = "cell">
2
</div>
<div class = "cell">
3
</div>
<div class = "cell">
4
</div>
<div class = "cell">
5
</div>
<div class = "cell">
6
</div>
<div class = "cell">
7
</div>
<div class = "cell">
8<
</div>
</div>
</div>
</body>
</html>
Цифры не обязательно должны быть центрированы, но синие квадраты, содержащие цифры, делают это. Также ваше решение полностью игнорирует требование соотношения сторон 1/1.
Я думаю, это проще, чем вы думаете, и вы ближе, чем вы думаете. В приведенном ниже фрагменте я удалил ненужные div-оболочки и добавил flexbox для центрирования содержимого ячейки.
.grid {
border: 3px solid black;
resize: both;
overflow: hidden;
display: grid;
max-width: 200px;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.grid > * {
margin: auto;
box-sizing: border-box;
border: 5px solid blue;
background-color: rgb(136, 136, 255);
aspect-ratio: 1;
max-height: 100%;
width: 100%;
overflow: hidden;
/* center the cell content in both directions */
display: flex;
justify-content: center;
align-items: center;
}
<div class = "grid">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
Спасибо! Это почти правильно, но ваше решение не сохраняет соотношение сторон 1/1, когда ширина больше высоты i.imgur.com/Z0grXRy.png
Также я хотел бы отметить, что числа в ячейке не имеют значения, их не нужно центрировать, извините, если я не совсем ясно выразился в своем сообщении. Я отредактировал его, чтобы больше не включать цифры.
Синий квадрат должен быть вертикально центрирован в своей строке, что правильно в вашем решении, но как только мы доберемся до соотношения сторон, при котором ширина больше высоты, ваше решение ломается.
@kess Я не вижу никаких проблем с тем, что соотношение сторон больше в ширину, чем в высоту; восемь ящиков остаются в центре. Включите проверку сетки в инструментах разработчика браузера и увидите пунктирные линии: i.stack.imgur.com/gDkgh.png Похоже, единственная проблема заключается в том, что восемь полей не остаются квадратными?
@TylerH «Похоже, единственная проблема, с которой вы столкнулись, это то, что восемь полей не остаются квадратными?» Да, это единственная проблема
@кесс Спасибо; Я добавил этот критерий в ваш список в вопросе, поскольку раньше он отсутствовал.
Извини. Пропустил изменяемый размер.
После нескольких часов проб и ошибок мне удалось найти решение.
Никаких оберток, никаких flexbox, никаких таблиц, никаких контейнерных запросов, только сетка и ее дочерние элементы.
.grid {
border: 3px solid black;
resize: both;
overflow: hidden;
display: grid;
width: 100px;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.cell {
box-sizing: border-box;
border: 5px solid blue;
background-color: rgb(136, 136, 255);
overflow: hidden;
aspect-ratio: 1/1;
/* keep the aspect ratio while filling as much space as possible */
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
padding: 0;
margin: 0;
/* center the element */
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class = "grid">
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
<div class = "cell"></div>
</div>
</body>
</html>
Мне непонятно, почему сетке дается больше, чем ширина и количество столбцов. Настройка строк кажется избыточной, если мы установили высоту ячеек по отношению к их ширине (соотношение сторон: 1/1).
Этот фрагмент разделяет все до самого необходимого. Очевидно, что если вам нужно больше структуры, чтобы иметь дело с тем, что вы хотите поместить в ячейку, которую можно добавить, но она останется внутри ячейки и не имеет отношения к получению базового макета сетки, который вы хотите.
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
width: 100px;
border: 3px solid black;
}
.grid>* {
width: 100%;
aspect-ratio: 1 / 1;
border: solid blue 3px;
box-sizing: border-box;
background-color: #8080ff;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class = "grid">
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
</div>
</body>
Мое текущее решение работает отлично, но у меня есть несколько проблем с ним. это ли не оксюморон