在调整大小的容器内重新排列网格项,保持一个图块不变

时间:2018-06-24 19:55:06

标签: javascript jquery css

我有一个网格,该网格的设计具有固定的宽度和高度。参见下图。

enter image description here

此网格必须适用于所有屏幕尺寸,同时将网格中的项目保持在相同位置。

我的代码当前根据设计的原始宽度/高度来调整这些项目的大小,并使其适应新的宽度/高度。

尽管在下面的示例中它们的位置不正确,但该计算确实起作用。

我遇到的困难是,我需要将504x504的中心网格图块设为静态,并在考虑这一点的情况下对其进行调整。

当前所有项目,包括居中调整的项,我只想停止居中调整的项,而其他项目则删除/增加其宽度/高度的差异。

这很难解释,请让我知道是否可以添加更多细节。

const initalWidth = 1043;
const initialHeight = 708;

const resize = (baseDimension, newDimension, itemDimension) => {
  const diff = ((baseDimension - newDimension) / baseDimension) * 100;

  return (Math.ceil(diff) / 100) * itemDimension;
}


const update = () => {
  const newWidth = jQuery(document).width();
  const newHeight = jQuery(document).height();

  jQuery('.grid').css({
    width: newWidth,
    height: newHeight
  })
  
  jQuery('.grid-item').each((i, item) => {
    const itemWidth = jQuery(item).data('width');
    const itemHeight = jQuery(item).data('height');

    const widthDiff = resize(initalWidth, newWidth, itemWidth);
    const heightDiff = resize(initialHeight, newHeight, itemHeight);
  	

    jQuery(item).width(Math.floor((itemWidth - widthDiff)));
    jQuery(item).height(Math.floor((itemHeight - heightDiff)));
  })
}

jQuery(document).ready(() => {
	// Run once
  update()
  
  // Run on resize
  jQuery(window).resize(update);
});
.grid{
  border: 1px solid blue;
  width: 100%;
  height: 100%;
}

.grid-item{
  background-color: red;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
  <div class="grid-item" data-width="257" data-height="249" style="background-color: red;"></div>
  <div class="grid-item" data-width="502" data-height="97" style="background-color: blue;"></div>
  <div class="grid-item" data-width="504" data-height="504" style="background-color: yellow;"></div>
  <div class="grid-item" data-width="275" data-height="254" style="background-color: brown;"></div>
  <div class="grid-item" data-width="275" data-height="254" style="background-color: pink;"></div>
  <div class="grid-item" data-width="275" data-height="198" style="background-color: orange;"></div>
  <div class="grid-item" data-width="275" data-height="247" style="background-color: purple;"></div>
  <div class="grid-item" data-width="502" data-height="97" style="background-color: green;"></div>
</div>

6 个答案:

答案 0 :(得分:4)

(另一种尝试,这次我想我得到了你想要的)

基本尺寸为1200x600

如果答案不能被接受,我想一个理由

*{
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.wrapper{
  display: flex;
  width: 100%;
  height: 100%;
}
.wrapper .column{
  display: flex;
  flex-direction: column;
  flex-grow: var(--flex-grow,0);
}
.wrapper .column .item{
  flex-grow: var(--flex-grow,0);
}
.wrapper .column .item.main{
  width: 200px;
  height: 200px;
  min-width: 200px;
  min-height: 200px;
}

.wrapper .column:first-child .item{ margin-left: 0; }
.wrapper .column:last-child .item{ margin-right: 0; }
.wrapper .column .item:first-child{ margin-top: 0; }
.wrapper .column .item:last-child{ margin-bottom: 0; }

/*----------------------------------*/
/* Only for demo styles */

@import "http://fonts.googleapis.com/css?family=Roboto";

html,body{
  height: 100%;
}

body{ 
  font-family: "Roboto";
  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper{
  resize: both;
  overflow: hidden;
}

.wrapper .column .item{
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  border: 1px solid blue;
  margin: 4px;
}
<div class="wrapper">
  <div class="column left" style="--flex-grow: 400">
    <div class="item" style="--flex-grow: 200">400x200</div>
    <div class="item" style="--flex-grow: 400">400x400</div>
  </div>
  <div class="column center">
    <div class="item" style="--flex-grow: 200">200x200</div>
    <div class="item main">
      <div>
        <b>Main Item</b><br>
        200x200
      </div>
    </div>
    <div class="item" style="--flex-grow: 200">200x200</div>
  </div>
  <div class="column right" style="--flex-grow: 600">
    <div class="item" style="--flex-grow: 300">600x300</div>
    <div class="item" style="--flex-grow: 300">600x300</div>
  </div>
</div>

(摘要最好在整页中查看)

相同的密码笔:https://codepen.io/devanshj/pen/xzBVwo

答案 1 :(得分:1)

我不确定我是否理解您的问题。我解决了如何防止黄色磁贴在页面上调整大小的方法,但是我不确定您如何定位磁贴。如果您可以为第一张图像中的图块上色,并以不同的窗口大小显示几个网格布局示例,那将对我有很大帮助。另外,请指定您的意思是“ ...,以及其他删除/增加其宽度/高度的区别。”

编辑:好的,我想我理解您的要求。我制作了两个“全局”变量yellowX和yellowY,它们保存了将应用于黄色图块的widthDiff和widthHeight。

然后我更改了您写入图块的方式以补偿调整大小

jQuery(item).width(Math.floor((itemWidth - widthDiff -yellowX/2)));
jQuery(item).height(Math.floor((itemHeight - heightDiff -yellowY/2))); 

这是我更新的代码,可防止黄色小块调整大小并对其进行补偿,希望这会有所帮助:

<!Doctype html>
<html>
    <head>
        <title>Stack Bounty</title>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    </head>
    <body>
        <script>
            //these vars show how much the yellow tile would have resized by if
            //it were constant
            var yellowX = 0;
            var yellowY = 0;

            const initalWidth = 1043;
            const initialHeight = 708;

            const resize = (baseDimension, newDimension, itemDimension) => {
            const diff = ((baseDimension - newDimension) / baseDimension) * 100;

      return (Math.ceil(diff) / 100) * itemDimension;
    }


    /*Updates the size of the tiles on window resize*/
    const update = () => {
      const newWidth = jQuery(window).width();
      const newHeight = jQuery(window).height();


        //set the dimensions of the grid
      jQuery('.grid').css({
        width: newWidth,
        height: newHeight
      })


        //itterate through each grid item
      jQuery('.grid-item').each((i, item) => {



          //edit by Wade King: if item is the yellow tile, don't resize
          if(jQuery(item).attr("class") == "grid-item const-item"){
              //set width and height of tile
              const itemWidth = 504;
              const itemHeight = 504
              jQuery(item).width(itemWidth);
              jQuery(item).height(itemHeight);

              //update how much the yellow tile should have resized by
              yellowX = resize(initalWidth, newWidth, itemWidth);
              yellowY = resize(initialHeight, newHeight, itemHeight);

          }else{
              //get the item width and height
            const itemWidth = jQuery(item).data('width');
            const itemHeight = jQuery(item).data('height');
              //calculate the decreace in dimensions
             const widthDiff = resize(initalWidth, newWidth, itemWidth);
            const heightDiff = resize(initialHeight, newHeight, itemHeight);

              //edit: apply the decrease in width and height and compensate for the yellow tile not resizing
            jQuery(item).width(Math.floor((itemWidth - widthDiff -yellowX/2)));
            jQuery(item).height(Math.floor((itemHeight - heightDiff -yellowY/2))); 
          }
          //end edit

      });
    }

    jQuery(document).ready(() => {
        // Run once
      update()

      // Run on resize
      jQuery(window).resize(update);
    });
        </script>

        <style>
    <!-- language: lang-css -->

    .grid{
        border: 1px solid blue;
        width: 100%;
        height: 100%;
    }

    .grid-item{
        background-color: red;
        float: left;
    }



        </style>





    <div class="grid">
        <!--edit by Wade King: added id names for future positioning and 
        and layout as well as a class 'const-item' to prevent resizing-->

      <div id = "red" class="grid-item" data-width="257" data-height="249" style="background-color: red;"></div>

      <div id = "blue" class="grid-item" data-width="502" data-height="97" style="background-color: blue;"></div>


      <div id = "yellow" class="grid-item const-item" data-width="504" data-height="504" style="background-color: yellow;"></div>


      <div id = "brown" class="grid-item" data-width="275" data-height="254" style="background-color: brown;"></div>


      <div id = "pink" class="grid-item" data-width="275" data-height="254" style="background-color: pink;"></div>


      <div id = "orange" class="grid-item" data-width="275" data-height="198" style="background-color: orange;"></div>


      <div id = "purple" class="grid-item" data-width="275" data-height="247" style="background-color: purple;"></div>


      <div id = "green" class="grid-item" data-width="502" data-height="97" style="background-color: green;"></div>

    </div>

    </body>
</html>

答案 2 :(得分:1)

如何使用px以外的单位。

https://www.w3schools.com/cssref/css_units.asp

vw相对于视口宽度的1%*

vh相对于视口高度的1%*

视口=浏览器窗口大小。如果视口为50厘米宽,则1vw = 0.5厘米。

.outer {
  background: red;
  width: 100vw;
}
.inner.col {
  display: inline-block;
  vertical-align: top;
}

.col-west {
  width: 20vw;
}
.col-middle {
  width: 50vw;
}
.col-east {
  width: 20vw;
}

.col-west > .row-1 {
  background: blue;
  height: 20vh;
}
.col-west > .row-2 {
  background: black;
  height: 40vh;
}
.col-west > .row-3 {
  background: white;
  height: 40vh;
}

.col-middle > .row-1 {
  background: silver;
  height: 10vh;
}
.col-middle > .row-2 {
  background: white;
  height: 30vh;
}
.col-middle > .row-3 {
  background: green;
  height: 60vh;
}
.col-east > .row-1 {
  background: yellow;
  height: 30vh;
}
<div class='outer'>
  <div class='inner col col-west'>
    <div class='inner row row-1'>
    
    </div><div class='inner row row-1'>
    
    </div><div class='inner row row-2'>
    
    </div><div class='inner row row-3'>
    
    </div>
  </div><div class='inner col col-middle'>
    <div class='inner row row-1'>
    
    </div><div class='inner row row-1'>
    
    </div><div class='inner row row-2'>
    
    </div><div class='inner row row-3'>
    
    </div>
  </div><div class='inner col col-east'>
    <div class='inner row row-1'>
    
    </div><div class='inner row row-1'>
    
    </div><div class='inner row row-2'>
    
    </div><div class='inner row row-3'>
    
    </div>
  </div>
 
</div>

答案 3 :(得分:1)

任何地方都可以满足您的要求?

这只是一个原型。如果您希望元素分开在页眉和内容之间或内容和页脚之间跳跃,那么这也是可能的。 (只需要一点时间)

body {
  margin: 0px;
  padding: 0px;
}

div {
  min-height: 10px;
}

.wrapper {
  margin: 0px;
  min-width: 106px;
  min-height: 150px;
  display: flex;
  flex-direction: row;
  resize: both;
  overflow: hidden;
  border: 1px dotted grey;
}

.left, .right {
  flex: 1 0 auto;
  flex-direction: column;
  background-color: #FFF;
}

.center {
  display: flex;
  flex-direction: column;
  background-color: #DDD;
}

.center .head,
.center .foot {
  border: 1px solid green;
  flex: 1 1 auto;
}

.center .content {
  width: 100px;
  height: 100px;
  background-color: #FA0;
  border: 1px solid red;
  flex: 0 0  auto;
}

.col1, .col2, .col3 {
  height: 30px;
  border: 1px solid blue;
}

.col1 { height: 50px; }
.col2 { height: 40px; }
.col2 { height: 70px; }
<div class='wrapper'>
  <div class='left'>
    <div class='col1'></div>
    <div class='col2'></div>
    <div class='col3'></div>
  </div>
  <div class='center'>
    <div class='head'>Header</div>
    <div class='content'>
      FIXED TO 100x100
    </div>
    <div class='foot'>Footer</div>
  </div>
  <div class='right'>
    <div class='col1'></div>
    <div class='col2'></div>
    <div class='col3'></div>
  </div>
</div>
<div style='text-align: right; padding-right: 10px; padding-top: 5px;'><b>Drag bottom right corner to resize! ↗</b></div>

答案 4 :(得分:1)

演示和代码:

https://codepen.io/devanshj/pen/QxYMjd(以下相同代码段)

带有Flexbox的纯CSS解决方案

不是您想要的网格,但是您可以通过对其进行修改来使其工作

使用方法:

  1. 通过--grow-ratio更改style,以更改放置主项后左右行左右分隔的空间比例
  2. .has-aspect-ratio上添加类.item并将其内容包装在.inner中,并通过--aspect-ratio添加style css变量
  3. 使用--gutter css变量更改装订线
  4. 使用--item-padding css变量来更改项目填充

PS:让我知道这是否不是您想要的东西,或者不是您想要的东西。我会改善的。

@import "http://fonts.googleapis.com/css?family=Roboto";

*{
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,body{
  height: 100%;
}

body{
  font-family: "Roboto";
}


.main-wrapper{
  display: flex;
  --gutter: 20px;
  --item-padding: 10px;
}

/* Flex stuff */
.main-wrapper .column{
  display: flex;
  flex-direction: column;
}
.main-wrapper .column{
  flex-grow: var(--grow-ratio,0);
}


/* Gutters */
.main-wrapper .column.right{
  padding-left: var(--gutter);
}
.main-wrapper .column.left{
  padding-right: var(--gutter);
}
.main-wrapper .item{
  margin-bottom: var(--gutter);
}
.main-wrapper .item:last-child{
  margin-bottom: 0;
}

/* Item */
.main-wrapper .item{
  padding: var(--item-padding);
  background-color: #555;
  color: #fff;
}
.main-wrapper .item.has-aspect-ratio{
  padding-top: calc(100% * var(--aspect-ratio));
  position: relative;
}
.main-wrapper .item.has-aspect-ratio .inner{
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  padding: var(--item-padding);
}

/* Main Item */
.main-wrapper .item.main{
  width: 500px;
  height: 500px;
}
<div class="main-wrapper">
  <div class="column left" style="--grow-ratio: 1">
    <div class="item">Item</div>
    <div class="item has-aspect-ratio" style="--aspect-ratio: 1;">
      <div class="inner">Item<br>Always in 1:1 aspect ratio</div>
    </div>
  </div>
  <div class="column center">
    <div class="item main">
      Main Item<br>
      Always 500&times;500<br><br>
      
      Left and right columns are in 1:1.5 ratio.
    </div>
    <div class="item">Item</div>
  </div>
  <div class="column right" style="--grow-ratio: 1.5">
    <div class="item">Item</div>
    <div class="item has-aspect-ratio" style="--aspect-ratio: 0.7">
      <div class="inner">
        Item<br>Always in 1:0.7 aspect ratio</div>
      </div>
    </div>
  </div>
</div>

答案 5 :(得分:0)

我想我会用CSS解决它。

使用媒体查询,以便当您接近504px宽度时再执行其他操作,然后在窗口更宽时执行其他操作。 在CSS中,您还可以将对象的宽度设置为calc(50%-504px);