Auto-growing margins when screen width get stretch

2020-08-21 05:41发布

I have a list (<ul />) that I try to display as a grid. The cells have a fixed width (let's say 100px): the number of cols and rows depends then on the screen resolution.

When the screen has a large width, there are many columns but few lines:

   ______________________________________________________________
  |   ___________    ___________    ___________    ___________   |
  |  |           |  |           |  |           |  |           |  |
  |  |    #1     |  |    #2     |  |    #3     |  |    #4     |  |
  |  |<- 100px ->|  |<- 100px ->|  |<- 100px ->|  |<- 100px ->|  |
  |  |           |  |           |  |           |  |           |  |
  |  |___________|  |___________|  |___________|  |___________|  |
  |   ___________                                                |
  |  |           |                                               |
  |  |    #5     |                                               |
  |  |<- 100px ->|                                               |
  |  |           |                                               |
  |  |___________|                                               |
  |______________________________________________________________|

When the screen has a small width, there are few columns but many lines:

               ________________________________
              |   ___________    ___________   |
              |  |           |  |           |  |
              |  |    #1     |  |    #2     |  |
              |  |<- 100px ->|  |<- 100px ->|  |
              |  |           |  |           |  |
              |  |___________|  |___________|  |
              |   ___________    ___________   |
              |  |           |  |           |  |
              |  |    #3     |  |    #4     |  |
              |  |<- 100px ->|  |<- 100px ->|  |
              |  |           |  |           |  |
              |  |___________|  |___________|  |
              |   ___________                  |
              |  |           |                 |
              |  |    #5     |                 |
              |  |<- 100px ->|                 |
              |  |           |                 |
              |  |___________|                 |
              |________________________________|

This is actually almost working: see this fiddle.

Almost, because as you can notice, when you're stretching the width, a blank space may appear on the right of the grid. This is because of the float: left CSS property, and is quite understandable.

But, is there any way to distribute this blank space between the cells, i.e. automatically increase the margins between the cells, until there is enough space to fit a new cell?

In other words, there is currently a fixed margin of 15px, and I'm looking for a kind of min-margin of 15px, that auto-grows while stretching the width, and goes back to 15px once a new cell fitted the first row.

To illustrate, instead of:

 ___________________________________________________________________
|   ___________    ___________    ___________    ___________        |
|  |           |  |           |  |           |  |           |       |
|  |    #1     |  |    #2     |  |    #3     |  |    #4     | BLANK |
|  |<- 100px ->|  |<- 100px ->|  |<- 100px ->|  |<- 100px ->| SPACE |
|  |           |  |           |  |           |  |           |       |
|  |___________|  |___________|  |___________|  |___________|       |
|   ___________                                                     |
|  |           |                                                    |
|  |    #5     |                                                    |
|  |<- 100px ->|                                                    |
|  |           |                                                    |
|  |___________|                                                    |
|___________________________________________________________________|

Having something like:

 ___________________________________________________________________
|    ___________     ___________     ___________     ___________    |
|   |           |   |           |   |           |   |           |   |
|   |    #1     |   |    #2     |   |    #3     |   |    #4     |   |
|   |<- 100px ->|   |<- 100px ->|   |<- 100px ->|   |<- 100px ->|   |
|   |           |   |           |   |           |   |           |   |
|   |___________|   |___________|   |___________|   |___________|   |
|    ___________                                                    |
|   |           |                                                   |
|   |    #5     |                                                   |
|   |<- 100px ->|                                                   |
|   |           |                                                   |
|   |___________|                                                   |
|___________________________________________________________________|

See, the margins are larger in the second illustration, so there is no blank space anymore.

Is there any solution?

Please note that the #5 cell has to be left-aligned too, i.e. an align-center CSS property won't suit my needs (as far as I know).

Moreover, I'll be using jQuery 1.10 and Bootstrap 3, so any solution using one (or more) of these libraries is also welcomed ;)

3条回答
Emotional °昔
2楼-- · 2020-08-21 06:11

I created a jQuery script that fixes your problem. See this fiddle. I wrote the script where you do not have to change it at all. You just set your minimum margin as the margin in the CSS and add as many <li> elements you want.

function setMargin() {
  ulWidth = $('ul').innerWidth();
  boxWidth = $('li').outerWidth();
  boxMargin = parseInt($('li').css('margin'));
  maxBoxNum = $("ul li").length;
  boxNum = Math.floor((ulWidth / (boxWidth + boxMargin)));
  totalMargin = ulWidth - (boxNum * boxWidth);
  eachMargin = totalMargin / (boxNum + 1);
  if (eachMargin < boxMargin) {
    boxNum -= 1;
    totalMargin = ulWidth - (boxNum * boxWidth);
    eachMargin = totalMargin / (boxNum + 1);
  }
  if (boxNum > maxBoxNum) {
    boxNum = maxBoxNum;
    totalMargin = ulWidth - (boxNum * boxWidth);
    eachMargin = totalMargin / (boxNum + 1);
  }
  $('li').css('margin-left', eachMargin);
}

$(document).ready(function() {
  setMargin();
});

$(window).resize(function() {
  setMargin();
});
ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

li {
  width: 100px;
  height: 100px;
  margin: 15px 0;
  padding: 0;
  border: solid 1px black;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul>
  <li>#1</li>
  <li>#2</li>
  <li>#3</li>
  <li>#4</li>
  <li>#5</li>
</ul>

查看更多
啃猪蹄的小仙女
3楼-- · 2020-08-21 06:12

If you can use width in percents and know that grid cells are more than 3 - the best way is to use media queries like this fiddle. You will fill empty margins by cell size increase.

查看更多
淡お忘
4楼-- · 2020-08-21 06:25

You can achieve your goal using only CSS. I am talking about media queries. Here is a DEMO I made. It shows you can use calculation to position your squares with equal margins between each other. The margin between elements and window is also the same.

I didn't write the code for screens wider than 751px though but you get the idea. Here is the code :

html,
body {
  margin: 0;
  padding: 0;
  min-width: 150px;
}

.wrap {
  float: left;
  position: relative;
}

.foto {
  width: 150px;
  height: 150px;
  background: gold;
  position: absolute;
}

#warning {
  display: none;
}

@media screen and (min-width: 631px) {
  .wrap {
    width: 20%;
    padding-bottom: 25%;
  }
  .wrap:nth-child(4n+2),
  .wrap:nth-child(4n+3) {}
  .wrap .foto {
    top: -75px;
    margin-top: 100%;
    right: -30px;
  }
  .wrap:nth-child(4n+2) {
    margin: 0 5% 0 7.5%;
  }
  .wrap:nth-child(4n+3) {
    margin-right: 7.5%;
  }
  .wrap:nth-child(4n+2) .foto {
    left: 50%;
    margin-left: -75px;
  }
  .wrap:nth-child(4n+3) .foto {
    right: 50%;
    margin-right: -75px;
  }
  .wrap:nth-child(4n) .foto {
    left: -30px;
  }
  #container {
    margin-top: -45px;
  }
}

@media screen and (min-width: 481px) and (max-width: 631px) {
  .wrap {
    width: 25%;
    padding-bottom: 33.3%;
  }
  .wrap:nth-child(3n+2) {
    margin: 0 12.5%;
  }
  .wrap .foto {
    top: -75px;
    margin-top: 100%;
    right: -37px;
  }
  .wrap:nth-child(3n+2) .foto {
    left: 50%;
    margin-left: -75px;
  }
  .wrap:nth-child(3n) .foto {
    left: -37px;
  }
  #container {
    margin-top: -37px;
  }
}

@media screen and (min-width: 331px) and (max-width: 480px) {
  .wrap {
    width: 33.3%;
    padding-bottom: 50%;
    clear: left;
  }
  .wrap:nth-child(even) {
    float: right;
    clear: right;
  }
  .wrap .foto {
    top: -75px;
    margin-top: 100%;
    right: -50px;
  }
  .wrap:nth-child(even) .foto {
    left: -50px;
  }
  .wrap:nth-child(4n+3) .foto,
  .wrap:nth-child(4n+4) .foto {
    bottom: -75px;
    margin-bottom: 100%;
  }
  #container {
    margin-top: -25px;
  }
}

@media screen and (max-width: 330px) {
  .wrap {
    width: 50%;
    padding-bottom: 100%;
    clear: left;
  }
  .wrap:nth-child(odd) .foto {
    right: -75px;
    bottom: 0;
    bottom: -75px;
    margin-bottom: 100%;
  }
  .wrap:nth-child(even) .foto {
    top: 0px;
    right: -75px;
    top: -75px;
    margin-top: 100%;
  }
}

@media screen and (min-width: 751px) {
  #warning {
    color: #fff;
    display: block;
    position: fixed;
    width: 100%;
    height: 50%;
    top: 25%;
    left: 0;
    background: #000;
    text-align: center;
    font-size: 30px;
  }
<div id="container">
  <div class="wrap">
    <div class="foto">1</div>
  </div>
  <div class="wrap">
    <div class="foto">2</div>
  </div>
  <div class="wrap">
    <div class="foto">3</div>
  </div>
  <div class="wrap">
    <div class="foto">4</div>
  </div>
  <div class="wrap">
    <div class="foto">5</div>
  </div>
  <div class="wrap">
    <div class="foto">6</div>
  </div>
  <div class="wrap">
    <div class="foto">7</div>
  </div>
  <div class="wrap">
    <div class="foto">8</div>
  </div>
  <div class="wrap">
    <div class="foto">9</div>
  </div>
  <div class="wrap">
    <div class="foto">10</div>
  </div>
  <div class="wrap">
    <div class="foto">11</div>
  </div>
  <div class="wrap">
    <div class="foto">12</div>
  </div>
  <div class="wrap">
    <div class="foto">13</div>
  </div>
  <div class="wrap">
    <div class="foto">14</div>
  </div>
  <div class="wrap">
    <div class="foto">15</div>
  </div>
</div>

<!-- FOLLOWING JUST FOR THE DEMO -->

<div id="warning">I haven't written the code for windows bigger than 751px.<br/> You must resize this window under 751px.</div>

查看更多
登录 后发表回答