CSS grid square layout [duplicate]

人走茶凉 提交于 2019-12-17 06:16:11

问题


I am trying to create grid/layout consists of squares. Four squares in each row. Squares can't distort on screen resize. Width and height must be the same all the time (I don't want fixed values). I must use CSS grid. Can anyone help me ?

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 5px;
}
.container div {
  background-color: red;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

回答1:


With CSS only you could use a pseudoelement to keep always the aspect ratio to 1:1 , e.g.

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 5px;
}
.container div {
  background-color: red;
}

.container div::before {
  content: "";
  padding-bottom: 100%;
  display: inline-block;
  vertical-align: top;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>



回答2:


For the fun, curiosity of grid behavior and to avoid a pseudo element,

You may also set an height equal to the width of your grid container, the grid system will automaticly stretch the rows.

A good reminder to mind :

https://css-tricks.com/snippets/css/complete-guide-grid/

and examples https://gridbyexample.com/


working example if your grid uses entire browser's width

  * {
  margin: 0;
  padding: 0;
}

.container {
  display: grid;
  height: calc(50vw - 5px);  /*instead playing around with grid gap gap */
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

.container div {
  /* bg to show i'm squarred or not ? */
  background-image: linear-gradient( 45deg, transparent 50%, rgba(0, 0, 0, 0.5) 50%);
 
 margin: 0 5px 5px 0;  /*instead playing around with grid gap gap */
  background-color: red;
}


/* extra for demo, not needed */

.container {
  counter-reset: test;
}

.container div {
  display: flex;  /* or grid */
}

.container div:before {
  counter-increment: test;
  content: 'Div N°:'counter(test)' -';
  margin: auto;/* center me */
  color: yellow;
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

A codepen to fork or play with




回答3:


Another trick where you can put any content inside without breaking the ratio. The idea is to have the grid inside a big square that you divide into small squares:

.container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr 1fr;
  grid-gap: 5px;
}

.container div {
  background-color: red;
}

body:before {
  content: "";
  display: block;
  padding-top: 100%;
}

body {
  position: relative;
  margin: 0;
}

img {
  max-width: 100%;
  max-height: 100%;
}
<div class="container">
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div></div>
</div>

Another syntax without position:absolute where you can rely on the stretch feature of flexbox:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr 1fr;
  grid-gap: 5px;
  flex-grow:1;
}

.container div {
  background-color: red;
}

body:before {
  content: "";
  padding-top: 100%;
}

body {
  display:flex;
}

img {
  max-width: 100%;
  max-height: 100%;
}
<div class="container">
<div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div></div>
</div>

You can control the limit of rows. In the above I made them 4, we can have only 2 by making the padding 50% instead of 100%. We will have a big rectangle inside where will have 8 squares (4 in each row).

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  grid-gap: 5px;
  flex-grow:1;
}

.container div {
  background-color: red;
}

body:before {
  content: "";
  padding-top: 50%;
}

body {
  display:flex;
  margin: 0;
}

img {
  max-width: 100%;
  max-height: 100%;
}
<div class="container">
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
</div>

You can control the number of rows using CSS variables:

:root {
  --n:6;
}

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-template-rows: repeat(var(--n),1fr);
  grid-gap: 5px;
  flex-grow:1;
}

.container div {
  background-color: red;
}

body:before {
  content: "";
  padding-top: calc(var(--n) * 25%);
}

body {
  display:flex;
}

img {
  max-width: 100%;
  max-height: 100%;
  display:block;
}
<div class="container">
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
</div>

We can also add a control on the number of columns by adding another variable to have something more generic:

:root {
  --n:6;
  --m:6;
}

.container {
  display: grid;
  grid-template-columns: repeat(var(--m),1fr);
  grid-template-rows: repeat(var(--n),1fr);
  grid-gap: 5px;
  flex-grow:1;
}

.container div {
  background-color: red;
}

body:before {
  content: "";
  padding-top: calc(var(--n)/var(--m) * 100%);
}

body {
  display:flex;
}

img {
  max-width: 100%;
  max-height: 100%;
}
<div class="container">
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here</div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div></div>
  <div></div>
  <div><img src="https://picsum.photos/200/300?image=1069"></div>
  <div></div>
  <div><img src="https://picsum.photos/200/200?image=1062"></div>
  <div>any contet here any contet here</div>
  <div></div>
  <div></div>
</div>



回答4:


** @fcalderan's answer solves the issue and all credit reserved. **

This obviously breaks the square shape, but if you would be using any text a small adjustment will work in your favor. You could rather use the ::after pseudo element to not push down or split potential content. Changing to display: block also removes the necessity of vertical-aling: top as far as I know.

To further preserve the aspect ratio when using text, I'd make the text position: absolute.

See the snippet below when using ::before vs. ::after to illustrate my point.

.container,
.container2 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 5px;
}
.container div {
  background-color: red;
}

.container div::before {
  content: "";
  padding-bottom: 100%;
  display: inline-block;
  vertical-align: top;
}

.container2 div::after {
  content: "";
  padding-bottom: 100%;
  display: block;
}

.container2 .text {
  position: absolute;  
}

.container2 div {
  background-color: green;
  position: relative;
  overflow: hidden;
}
<div class="container">
  <div>
    <div class="text">Here is some text.</div>
  </div>
  <div>
    <div class="text">Here is some more text.</div>
  </div>
  <div>
    <div class="text">Here is some longer text that will break how this looks.</div>
  </div>
</div>
  
  <hr>
  <div class="container2">
  <div>
    <div class="text">Here is some text.</div>
  </div>
  <div>
    <div class="text">Here is some more text.</div>
  </div>
  <div>
    <div class="text">Here is some longer text that will break how this looks.</div>
  </div>
</div>


来源:https://stackoverflow.com/questions/54927180/css-grid-square-layout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!