Переполнение не вызвано положением: абсолютное - PullRequest
2 голосов
/ 27 апреля 2020

В этом макете я использую сетку CSS с position: absolute, чтобы показать список элементов, наложенных поверх карты. Моя проблема в том, что overflow-x: auto не запускается, вызывая отображение только первых нескольких элементов.

При изменении grid-auto-columns списка с minmax(auto, 1fr) на minmax(0, 1fr) я получаю полосу прокрутки, однако элементы затем накладываются друг на друга.

CodePen: https://codepen.io/tgel0/pen/ZEbKZvb

.wrapper{
  display: grid;
  grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  height: 100vh;
  width: 100vw;
  grid-template-areas:
  "side side main main"
  "side side main main"
}

.side {
  grid-area: side;
  display: grid;
  grid-template-columns: 1fr;
  padding: 20px;
  color: #fff;
  background-color: green;
}


.main {
  grid-area: main;
  display: grid;
  background-color: gray;
  grid-template-columns: 1px 1fr 1px;
  gap: 20px;
  position: relative;
  overflow-y: auto;
  overflow-x: hidden;
}

.main > * {
  grid-column: 1 / -1;
}

.map {
  background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
  height: 100%;
  overflow: auto;
}

.container-for-items {
  display: grid;
  grid-template-columns: 10px;
  grid-template-rows: 1fr;  
  grid-auto-columns: minmax(0, 1fr); /* minmax(auto, 1fr); */
  grid-auto-flow: column;
  grid-gap: 20px;
  padding: 20px;
  z-index: 99;
  position: absolute;
  bottom: 20px;
  overflow-x: auto;
}

container-for-items:before,
.container-for-items:after {
  content: '';
  width: 10px;
}

.item {
  display: grid; 
  background-color: white;
  border: 2px solid blue;
  padding: 25px;
  width: 300px;
  height: 150px;
}
<div class="wrapper">
  <div class="side">Don't scroll</div>
  <div class="main">
    <div class="map"></div>
    <ul class="container-for-items">
      <li class="item">This is item 1</li>
      <li class="item">This is item 2</li>
      <li class="item">This is item 3</li>
      <li class="item">This is item 4</li>
      <li class="item">This is item 5</li>
      <li class="item">This is item 6</li>
      <li class="item">This is item 7</li>
      <li class="item">This is item 8</li>
      <li class="item">This is item 9</li>
      <li class="item">This is item 10</li>
      <li class="item">This is item 11</li>
    </ul>    
  </div>  
</div>

Ответы [ 2 ]

3 голосов
/ 28 апреля 2020

Чтобы включить прокрутку, элемент должен соответствовать двум правилам:

  1. предел
  2. overflow установлен на auto или scroll

В вашем случае правило 1 не соблюдается.

Мы можем просто добавить ширину к сетке, и она будет работать как положено.

.wrapper{
  display: grid;
  grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  height: 100vh;
  width: 100vw;
  grid-template-areas:
  "side side main main"
  "side side main main"
}

.side {
  grid-area: side;
  display: grid;
  grid-template-columns: 1fr;
  padding: 20px;
  color: #fff;
  background-color: green;
}


.main {
  grid-area: main;
  display: grid;
  background-color: gray;
  grid-template-columns: 1px 1fr 1px;
  gap: 20px;
  position: relative;
  overflow-y: auto;
  overflow-x: hidden;
}

.main > * {
  grid-column: 1 / -1;
}

.map {
  background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
  height: 100%;
  overflow: auto;
}

.container-for-items {
  display: grid;
  grid-template-columns: 10px; /* this is making the first column shorter than the grid item so it will be overlapped by the next element */
  grid-template-rows: 1fr;  
  /* removed columns rule */
  grid-auto-flow: column;
  grid-gap: 20px;
  padding: 20px;
  z-index: 99;
  position: absolute;
  bottom: 20px;
  overflow-x: auto;
  
  width:100%; /* Added */
}

container-for-items:before,
.container-for-items:after {
  content: '';
  width: 10px;
}

.item {
  display: grid; 
  background-color: white;
  border: 2px solid blue;
  padding: 25px;
  width: 300px;
  height: 150px;
}
<div class="wrapper">
  <div class="side">Don't scroll</div>
  <div class="main">
    <div class="map"></div>
    <ul class="container-for-items">
      <li class="item">This is item 1</li>
      <li class="item">This is item 2</li>
      <li class="item">This is item 3</li>
      <li class="item">This is item 4</li>
      <li class="item">This is item 5</li>
      <li class="item">This is item 6</li>
      <li class="item">This is item 7</li>
      <li class="item">This is item 8</li>
      <li class="item">This is item 9</li>
      <li class="item">This is item 10</li>
      <li class="item">This is item 11</li>
    </ul>    
  </div>  
</div>

В приведенном выше фрагменте вы можете видеть, что я удалил grid-auto-columns все вместе. Почему?

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

minmax (auto, 1fr) ;

Что в основном совпадает с 1fr означает, что сетка track/columns не может быть меньше, чем содержимое элемента сетки, это предотвратит сокращение сетки, но вы не увидите ее из-за переполнения скрыт на .main, поэтому нет полос прокрутки.


Изменение на minmax(0, 1fr); в этом случае track/columns может быть таким, каким оно должно быть, поэтому, если у нас всего несколько элементов, track/columns будет равен элементу сетки.

Однако, если мы продолжим добавлять элементы, сетка будет продолжать расти, в конце концов она остановится, когда достигнет правого края своего родителя, track/columns внутри уменьшится до размеров (1fr), но элементы сетки будут перекрываться, потому что они шире, чем track/columns

В этом случае сетка перестает расти, потому что ей нет дела до любезности содержимого minmax(0, 1fr); и overflow:auto, поэтому она возвращается к нормальному поведению переноса пробелов но поскольку это сетка, она не может обернуться, поэтому они перекрываются.

Демо

body * {
  padding: 10px;
  border: 1px solid;
}

[positioned] {
  border: 1px solid;
  position: relative;
  background: pink;
  height: 150px;
  width: 300px;
  /* white-space:nowrap; un comment this line to see */
}

[grid] {
  background: red;
  position: absolute;
}

[item] {
  background: orange;
  display: inline-block;
  width: 100px;
  height: 100px;
  animation :grow 10s linear infinite alternate;
}

@keyframes grow {
  from {
    width: 10px;
  }
}
As childs grow the parent's grow as well but it stops when it hits the right edge of the parent, Normal overflow behaviour 
<div positioned>
  <div grid>
    <div item></div>
    <div item></div>
    <div item></div>
  </div>
</div>
3 голосов
/ 27 апреля 2020

В этом макете много чего происходит - вложенные сетки, абсолютное позиционирование, псевдоэлементы, фоновое изображение и много, казалось бы, ненужного кода - поэтому алгоритмы могут конфликтовать (например, я продолжаю получать разные визуализации в Chrome / FF против Край).

Я думаю, что самое простое решение - удалить весь ненужный код, полностью расположить изображение (не контейнер) и упростить структуры сетки.

Никаких изменений в HTML не требуется.

.wrapper{
  display: grid;
  grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  height: 100vh;
  /* width: 100vw; */
  grid-template-areas:
  "side side main main"
  "side side main main"
}

.side {
  grid-area: side;
  display: grid;
  /* grid-template-columns: 1fr; */
  padding: 20px;
  color: #fff;
  background-color: green;
}

.main {
  grid-area: main;
  display: grid;
  background-color: gray;
  /* grid-template-columns: 1px 1fr 1px; */
  gap: 20px;
  position: relative;
  /* overflow-y: auto; */
  /* overflow-x: hidden; */
}

/* .main > * {
  grid-column: 1 / -1;
} */

.map {
  background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
  height: 100vh; /* adjustment */
  width: 100%; /* new */
  position: absolute; /* new */
  /* overflow: auto; */
}

.container-for-items {
  display: grid;
  /* grid-template-columns: 10px; */
  grid-template-rows: 150px; /* adjustment; from grid items */  
  grid-auto-columns: 300px; /*  adjustment; from grid items */
  /* grid-auto-flow: column; */
  grid-gap: 20px;
  padding: 20px;
  z-index: 99;
  /* position: absolute; */
  /* bottom: 20px; */
  align-self: end; /* new */
  overflow-x: auto;
  position: relative; /* for Edge */
}

/* reverse collapsing margin at container end */
/* https://stackoverflow.com/q/38993170/3597276 */
/* .container-for-items:before (unnecessary; remove) */
.container-for-items:after {
  content: '';
  width: 10px;
  grid-row: 1;
}

.item {
  grid-row: 1; /* new */
  display: grid; 
  background-color: white;
  border: 2px solid blue;
  padding: 25px;
  /* width: 300px;  */ /* move to grid-template-columns */
  /* height: 150px; */ /* move to grid-template-rows */
}

/* new */
body {
  margin: 0;
}

* {
  box-sizing: border-box;
}
<div class="wrapper">
  <div class="side">Don't scroll</div>
  <div class="main">
    <div class="map"></div>
    <ul class="container-for-items">
      <li class="item">This is item 1</li>
      <li class="item">This is item 2</li>
      <li class="item">This is item 3</li>
      <li class="item">This is item 4</li>
      <li class="item">This is item 5</li>
      <li class="item">This is item 6</li>
      <li class="item">This is item 7</li>
      <li class="item">This is item 8</li>
      <li class="item">This is item 9</li>
      <li class="item">This is item 10</li>
      <li class="item">This is item 11</li>
    </ul>
  </div>
</div>

пересмотренный кодовый блок

...