Проблемы с созданием сетки flexbox


person Alkahna    schedule 18.05.2017    source источник
comment
Нет, только с помощью flexbox это невозможно. Вам придется попробовать экспериментальную сетку CSS. Что делает flexbox, так это то, что он дает вам простой способ гибкого распределения элементов, но не делает это двуосно (как вы хотите в сетке).   -  person Terry    schedule 18.05.2017
comment
хорошо, спасибо за эту информацию. Я открыт для всего, кроме редактирования структуры html/php joomla.   -  person Alkahna    schedule 18.05.2017


Ответы (3)


Желаемый макет не может быть достигнут с помощью flexbox. Причины описаны здесь:

Однако макет относительно прост с CSS Grid.

На самом деле существует несколько методов построения макета с помощью Grid. Я буду использовать grid-template-areas, которое позволяет размещать элементы с помощью ASCII-арта.

.wrapper {
  display: grid;
  height: 100vh;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: 
     " heading heading "
     "  left_ right1   "
     "  left_ right2   "
     "  left_ right3   "
     "  left_ right4   "
}

.page-header { grid-area: heading; }
.right_1     { grid-area: right1;  }
.right_2     { grid-area: right2;  }
.right_3     { grid-area: right3;  }
.right_4     { grid-area: right4;  }
.left        { grid-area: left_;   } /* "left" is a pre-defined CSS keyword,
                                         so it may not work */
@media ( max-width: 800px ) {
  .wrapper { 
     grid-template-columns: 1fr;
     grid-template-areas: 
        " heading "
        "  left_  "
        "  right1 "
        "  right2 "
        "  right3 "
        "  right4 "
     }
}

/* non-essential decorative styles */
.page-header { background-color: red; }
.right_1     { background-color: chartreuse; }
.right_2     { background-color: aqua; }
.right_3     { background-color: skyblue; }
.right_4     { background-color: black; color: white; }
.left        { background-color: cornsilk; }
body         { margin: 0; }
.wrapper > * {
  font-weight: bold;
  font-size: 1.5em;
  border: 1px solid black;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="wrapper">
  <div class="page-header">Heading</div>
  <h3 class="right_1">right_1</h3>
  <div class="right_2">right_2</div>
  <div class="left">form element</div>
  <h3 class="right_3">right_3</h3>
  <div class="right_4">right_4</div>
</div>

демонстрация jsFiddle

По сути, вот как это работает:

  1. Мы устанавливаем сетку на уровне блоков с помощью display: grid.
  2. С помощью grid-template-columns: 1fr 1fr мы говорим сетке создать два столбца. Модуль fr указывает контейнеру использовать доступное пространство. Это похоже на свойство flex-grow flexbox. Таким образом, оба столбца будут использовать всю ширину контейнера.
  3. Свойство grid-template-areas позволяет вам размещать именованные области сетки (которые вы определили) для создания визуального представления вашего макета с использованием графики ASCII.
  4. В медиа-запросе для небольших экранов мы удаляем один столбец и меняем порядок областей сетки.

Поддержка CSS Grid браузерами

  • Chrome — полная поддержка с 8 марта 2017 г. (версия 57)
  • Firefox — полная поддержка с 6 марта 2017 г. (версия 52)
  • Safari — полная поддержка с 26 марта 2017 г. (версия 10.1)
  • Edge — полная поддержка с 16 октября 2017 г. (версия 16)
  • IE11 - нет поддержки текущей спецификации; поддерживает устаревшую версию

Вот полная картина: http://caniuse.com/#search=grid

person Michael Benjamin    schedule 18.05.2017
comment
это звучит довольно хорошо, я добавлю этот код и проверю;) - person Alkahna; 18.05.2017
comment
работает довольно хорошо, я должен сказать. Единственное, что я пропустил, это height: 100vh; из .wrapper{..} наверху, потому что это вызвало переполнение содержимого <div class="wrapper">, что выглядело ужасно, но простое избавление от height: 100vh; делает свое дело ;) Осталось только заставить его работать на грани /IE как-то (пока не пробовал) - person Alkahna; 19.05.2017
comment
Вот почему я сначала выбрал flexbox, он поддерживает браузеры IE/Edge и Opera Mini/Android. - person Alkahna; 19.05.2017
comment
Еще одна вещь, над которой я сейчас работаю, — это ограничение размера элементов справа. Между right_1 и right_2, а также right_3 и right_4 есть большие промежутки (1/3 — заголовки, а 3/4 — соответствующий текст). - person Alkahna; 19.05.2017
comment
@Alkahna Это вызвано элементами h3, у которых есть поля по умолчанию. Установите их маржу на 0, и она исчезнет - person Ason; 20.05.2017
comment
У меня получилось работать с сеткой, спасибо, но я также хочу использовать решение flexbox в качестве запасного варианта из-за лучшей поддержки браузера (отредактировал мой вопрос выше) - person Alkahna; 24.05.2017

Вот один из способов решить эту проблему, основанный на существующей разметке и CSS Flexbox.

left должен иметь абсолютное позиционирование для просмотра рабочего стола, а page-header нужна фиксированная высота.

Если вы не хотите устанавливать фиксированную высоту, вам понадобится скрипт, который позаботится о вычислении высоты

html, body {
  margin: 0;
}
.wrapper {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.wrapper * {
  padding: 0 10px;
  margin: 0;
  border: 1px solid black;
  box-sizing: border-box;  
}
.page-header {
  height: 70px;
  width: 100%;
  background: red;
}
.right_1, .right_2, .right_3, .right_4 {
  flex: 1;
  width: 50%;
  margin-left: 50%;
  background: lightblue;
}
.left {
  position: absolute;
  left: 0;
  top: 70px;
  width: 50%;
  min-height: calc(100vh - 70px);
  background: yellow;
}
@media only screen and (orientation: portrait) {
  .wrapper * {
    width: 100%;
    margin: 0;
  }
  .left {
    position: static;
    flex: 1;
    min-height: auto;
    order: -1
  }
  .page-header {
    order: -2;
  }
}
<div class="wrapper">
  <div class="page-header">Heading</div>
  <h3 class="right_1">right_1</h3>
  <div class="right_2">right_2</div>
  <div class="left">form element</div>
  <h3 class="right_3">right_3</h3>
  <div class="right_4">right_4</div>
</div>

person Ason    schedule 18.05.2017
comment
Я также протестировал ваше решение и обнаружил, что медиа-запрос нуждается в некоторых корректировках для правильной работы: @media only screen and (max-width: 768px) { .wrapper * { width: 100% !important; margin: 0 !important; } .left { position: static !important; flex: 1; min-height: auto !important; order: -1 } } содержимое .wrapper переполняется .wrapper, но я продолжу исправлять это - person Alkahna; 19.05.2017
comment
@Alkahna Конечно, так и есть, так как я не делал никаких таких настроек. CSS Grid лучше, так как вы получаете более отзывчивое решение. Его обратная сторона, конечно, поддержка браузера. Если вы собираетесь использовать Flexbox, я рекомендую вам добавить небольшой скрипт, который отвечает за позиционирование/размер left. Я имею в виду, что это хороший компромисс, поскольку он не добавляет большой нагрузки на браузер. - person Ason; 19.05.2017
comment
@Alkahna Кстати, скрипт, конечно, не понадобится, если вы можете контролировать размер с помощью медиа-запросов. - person Ason; 19.05.2017
comment
Я заметил, что, поскольку у меня уже есть другие медиа-запросы, я просто продолжу их использовать и буду избегать как можно большего количества сценариев. У вас есть идея по моему редактированию моего исходного вопроса? - person Alkahna; 24.05.2017
comment
@Alkahna Это совершенно новый вопрос, поэтому отмените его и создайте новый с вашими новыми требованиями. И примите здесь того, кто решил этот вопрос лучше всего. - person Ason; 25.05.2017

Вероятно, самый простой способ изменить порядок элементов div, вы можете использовать для этой цели Jquery. Например:

$("#element1").before($("#element2"));

В итоге:

CSS:

#blocks {
    display: box;
    box-orient: vertical;
}
#b1 {
    box-ordinal-group: 2;
}
#b2 {
    box-ordinal-group: 3;
}

HTML:

<div id="blocks">
    <div id="b1">Block 1</div>
    <div id="b2">Block 2</div>
    <div id="b3">Block 3</div>
</div>

Он должен работать.

person Dawid Karasiewicz    schedule 18.05.2017