Центрирование содержимого сетки при выравнивании содержимого каждой строки по левому краю с произвольной шириной элемента / столбца - PullRequest
9 голосов
/ 17 июня 2020

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

enter image description here

Иногда контейнер становится меньше, чем ширина всех элементов:

enter image description here

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

enter image description here

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

enter image description here

Первоначально я пытался реализовать это с помощью FlexBox. После многих разочарований и выдергивания волос я понял, что это невозможно с FlexBox: { ссылка }

Другой ответ на той же странице предлагает использовать сетку CSS вместо flexbox. .

CSS grid дает немного другой результат, но меня это тоже устраивает:

enter image description here

Вот код, который делает это работа:

.red-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
  justify-content: center;
}

Этот код содержит множество ключевых слов, которые я не понимаю: grid-template-columns, repeat, auto-fit, minmax и max-content. Я попытался их прочитать, но потерпел неудачу. Ни одно из руководств и документов API не объясняет, как работает эта конкретная комбинация. Документы MDN слишком короткие и шифрованные c.

То, с чем я особенно борюсь с , - это 210px magi c номер. Зачем это нужно? (Эм, я знаю, что это необходимо, потому что спроектирован SP c, но это не помогает мне понять.)

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

По сути, я хочу:

  grid-template-columns: repeat(auto-fit, minmax(min-content, max-content));

, но это правило распознается браузерами как ошибочное.

Я наткнулся на этот ответ это объясняет, что использование min-content и max-content вместе запрещено SPE c в этом контексте. Предлагаемое решение - использовать Flexbox!

Л oop закрылся. Я вернулся к тому, с чего начал, ожидаю, что у меня теперь не хватает волос на голове для следующего раунда.

Как мне центрировать сетку, выравнивая по левому краю содержимое каждой строки, с элементами произвольной ширины?

Вот шаблон, с которым можно поиграть для вашего удобства: https://jsbin.com/vuguhoj/edit?html, css, вывод

Размер контейнера можно изменить, перетащив его за правый нижний угол.

PS Нет display: inline и float: left Пожалуйста.

.page {
  border: 1px solid black;
  overflow: hidden;
  resize: horizontal;
  max-width: 500px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max-content, 50px));
  justify-content: center;
}

.item {
  border: 1px solid black;
  margin: 1px;
}
<div class="page">
  <div class="grid">
    <div class="item">
      Foofoofoo
    </div>
    <div class="item">
      Bar
    </div>
    <div class="item">
      BazBaz
    </div>
    <div class="item">
      QuuxQuuxQuux
    </div>
  </div>
</div>

Ответы [ 6 ]

3 голосов
/ 20 июня 2020

В этом случае я вижу единственное решение - использовать JavaScript.

В этом коде мы получаем каждую ширину .item. Затем мы устанавливаем .flex width = total .item width. Если общая .item ширина меньше, чем .page ширина - мы устанавливаем .flex width = ((total .item width) - (last .item width)). Надеюсь, JS хорошо читается. Если вам нужно больше пояснений - можете дать в комментариях.

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

Этот фрагмент можно протестировать только при изменении размера окна браузера . Лучше регистрироваться с помощью полной страницы сниппета и консоли Chrome с режимом панели инструментов Devise. Или здесь https://jsfiddle.net/focusstyle/sh6dnLvt/1/

window.addEventListener("resize", function() {
  flexWidth();  
});

function flexWidth() {
  let page = document.querySelector('.page');
  let flex = document.querySelector('.flex');
  let totalWidth = biggesWidth = itemWidth = lastWidth = 0;
  let flexItem = document.querySelectorAll('.item');
  for (let i = 0; i < flexItem.length; i += 1) {
    itemWidth = flexItem[i].offsetWidth;
    if (biggesWidth<itemWidth) {
      biggesWidth = itemWidth;
    } 
    biggesWidth = flexItem[i].offsetWidth;
    totalWidth += itemWidth;
    lastWidth = itemWidth; 
  }
  if (totalWidth > page.clientWidth) {
    totalWidth = totalWidth - lastWidth;
  }
  totalWidth += 1;  
  flex.style.cssText = "min-width: "+biggesWidth+"px; max-width: "+totalWidth+"px;"; 
}
.page {
  border: 1px solid black;
  overflow: hidden;
  text-align: center;
}

.flex {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.item {
  border: 1px solid black;
}
<div class="page">
  <div class="flex">
    <div class="item">
      Foofoofoo
    </div>
    <div class="item">
      Bar
    </div>
    <div class="item">
      BazBaz
    </div>
    <div class="item">
      QuuxQuuxQuux
    </div>
  </div>
</div>
2 голосов
/ 22 июня 2020

CSS сеточный подход- root ответ - joe82

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(179px, max-content));
  grid-gap: 10px;
  justify-content: center;
  background: #999;
  overflow: hidden;
  padding: 10px;
}

.background {
  width: 179px;
  height: 64px;
  background: #99d9ea;
}

.background .child {
  border: 2px solid #000;
}

.background:nth-child(1) .child {
  width: 110px;
  height: 50px;
}

.background:nth-child(2) .child {
  width: 120px;
  height: 60px;
}

.background:nth-child(3) .child {
  width: 50px;
  height: 55px;
}

.background:nth-child(4) .child {
  width: 175px;
  height: 40px;
}
<div class="container">
    <div class="background"><div class="child"></div></div>
    <div class="background"><div class="child"></div></div>
    <div class="background"><div class="child"></div></div>
    <div class="background"><div class="child"></div></div>
</div>

Newb ie здесь!

Я признаю, что приведенный выше результат не тот результат, который вам нужен, но это моя лучшая попытка к нему, с использованием сеток CSS. Здесь вы можете понять, что если мы хотим сделать его адаптивным, тогда требуется минимальная ширина, после чего столбец (контент) будет перенесен на следующую строку, и эта ширина определяется здесь (grid-template-columns: repeat(auto-fit, minmax(204px, max-content));) 204px. Но из-за этого каждый столбец будет иметь как минимум такую ​​ширину, поэтому я представил фактический размер столбца с синим фоном и фактическое содержимое внутри границы. Я просто публикую его для вашего подтверждения и подхода, чтобы вы могли приблизиться к собственно ответу.

Кстати, Flex Approach- root идея - случайный COSMOS

.container {
  min-width: 130px;
  max-width: 340px;
  overflow: auto;
  background: #999;
  padding: 10px 40px;
  resize: horizontal;
  border: 1px solid #000;
}

.main-content {
  display: flex;
  flex-wrap: wrap;
  background: #fff;
  max-width: 340px;
  overflow: hidden;
}

.child {
  margin: 5px;
  padding: 5px;
  background: #99d9ea;
  border: 1px solid black;
}
<div class="container">
  <div class="main-content">
    <div class="child">Foofoofoo</div>
    <div class="child">Bar</div>
    <div class="child">BazBaz</div>
    <div class="child">QuuxQuuxQuux</div>
  </div>
</div>
Resize the window or the above div to see the results 

Выше указано, что div центрирован, а содержимое находится слева, но не изменяется в размере в соответствии с содержимым.

Мои личные мнение -

Вы должны использовать @media для того, чтобы заставить его реагировать так, как вы хотите, это похоже на кодирование для простого вывода, но оно может дать вам лучшее и удовлетворительные результаты вашего тяжелого труда и времени!

Пожалуйста, сообщите мне, если вы хотите, чтобы я отвечал за вас, я имею в виду, как демо-

С уважением, Ом Чаудхари

1 голос
/ 23 июня 2020

Давайте сначала разберемся с 210px. Когда вы пишете следующий код:

grid-template-columns: repeat(auto-fit, minmax(210px, max-content));

Браузер знает, когда обернуть элементы. Это гарантирует, что ваши элементы сетки всегда будут шире 210 пикселей или, по крайней мере, равны 210 пикселей.

Если в браузере доступна ширина 420 пикселей, он поместит 2 элемента в ряд. Если в браузере доступна ширина 630 пикселей, он поместит 3 элемента в ряд и так далее ...

Вы можете узнать о сетках CSS здесь

Если вы все еще не хотите иметь минимальный контент в 210 пикселей, вы всегда можете использовать медиа-запросы в CSS.

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

Надеюсь, это спасет часть ваших волос.

1 голос
/ 19 июня 2020

Если мы go вместо center, мы не получим left-align вещь:

.page {
  border: 1px solid black;
  max-width: 500px;
  resize: horizontal;
  overflow: hidden;
  display: flex;
  justify-content: center;
  padding: 0 50px;
}

.grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.item {
  border: 1px solid black;
  margin: 1px;
}
<div class="page">
  <div class="grid">
    <div class="item">Foofoofoo</div>
    <div class="item">Bar</div>
    <div class="item">BazBaz</div>
    <div class="item">QuuxQuuxQuux</div>
  </div>
</div>

Теперь с left-align (как в ответе @Michael Benjamin) он не выполняет вещи center:

.page {
  border: 1px solid black;
  max-width: 500px;
  resize: horizontal;
  overflow: hidden;
  display: flex;
  justify-content: center;
  padding: 0 50px;
}

.grid {
  display: flex;
  flex-wrap: wrap;
}

.item {
  border: 1px solid black;
  margin: 1px;
}
<div class="page">
  <div class="grid">
    <div class="item">Foofoofoo</div>
    <div class="item">Bar</div>
    <div class="item">BazBaz</div>
    <div class="item">QuuxQuuxQuux</div>
  </div>
</div>

Почему?

Потому что во втором коде и в коде @Michael Benjamin .grid технически centered. Visual : enter image description here

Смотрите, что весь div центрирован. Проблема в том, что div .grid не меняет свою ширину в зависимости от содержимого внутри него. Но в соответствии с шириной его родительского элемента div (.page).

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

0 голосов
/ 22 июня 2020

Я не знаю, упустил ли я что-то, но я думаю, что этого можно добиться с помощью flexbox.

Вы должны получить эту структуру:

<div class="container">
  <div class="row">
    <div class="item item-1"></div>
    <div class="item item-2"></div>
    <div class="item item-3"></div>
    <div class="item item-4"></div>
  </div>
</div>

где row имеет max size и margin: 0 auto (для центрирования)

Вот мой пример на Codepen

screen 1 экран 2

0 голосов
/ 17 июня 2020

У вас есть два доступных контейнера - .page и .grid.

Это позволяет распределить две задачи - центрирование и выравнивание по левому краю.

Используйте контейнер верхнего уровня для центрирования.

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

Вот концепция кода:

.page {
  display: grid;
  grid-template-columns: 50px 1fr 50px;
  border: 1px solid black;
  max-width: 500px;
}

.grid {
  grid-column: 2;
  justify-self: center;
  display: flex;
  flex-wrap: wrap;
}

.item {
  border: 1px solid black;
  margin: 1px;
}
<div class="page">
  <div class="grid">
    <div class="item">Foofoofoo</div>
    <div class="item">Bar</div>
    <div class="item">BazBaz</div>
    <div class="item">QuuxQuuxQuux</div>
  </div>
</div>

jsFiddle demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...