简体   繁体   中英

Resizing a div maintaining proportions

I imagine this has been asked before, so I'd be thankful if I could be re-directed to the answer (or given some advice).

So, the code below draws a 15 by 7 grid, and what I want is it to resize automatically, maintaining the proportions, every time I (a) resize the window or (b) load this in, say, a tablet or mobile phone.

Ie the result in the screen should be the full 15*7 grid. Here is the code (I tried bootstrap, but obviously did not use this properly). Thank you for your help.

 var stage = document.querySelector("#stage"); var pattern = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ] var SIZE = 60; var SPACE = 0; var ROWS = pattern.length; var COLUMNS = pattern[0].length; for (var row = 0; row < ROWS; row++) { for (var column = 0; column < COLUMNS; column++) { //Create a div HTML element called cell var cell = document.createElement("div"); //Set its CSS class to "cell" cell.setAttribute("class", "cell"); //Add the div HTML element to the stage stage.appendChild(cell); //Make it black if it's a "1" if (pattern[row][column] === 1) { cell.style.backgroundColor = "black"; } //Position the cell in the correct place //with 10 pixels of space around it cell.style.top = row * (SIZE + SPACE) + "px"; cell.style.left = column * (SIZE + SPACE) + "px"; } } 
 html, body { height: 100%; } #stage { position: relative; height: 100%; } .cell { position: absolute; width: 60px; height: 60px; border: 1px solid gray; background-color: white; } 
 <div class="container"> <div class="row"> <h1>Grid</h1> <div id="stage"></div> </div> </div> 

I'd recommend using a pseudo element with padding to handle aspect ratio for boxes, with an auto height. This works due to padding percentages being a percentage of the parent width, rather than height.

.cell:before{
  content: '';
  display: block;
  width: 100%;
  padding-top: 100%;
}

In your situation your cells will also need to be position by percentage rather than pixel values in your js.

fiddle: http://jsfiddle.net/zukrLbqp/1/

Another tip, bit off the original question, but there are other ways you could position your elements with css that would negate the need to do it in js at all. Let me know if you want me to go into how this works, but here's an example: http://jsfiddle.net/eys59y17/

Position absolute changed to display inline-block and a BR after each row end
now cells are sized 6vw x 6vw (eq to 60px for a 1000px window)
http://dx-creation.com/js/flexgrid.html

<style>
    html, body {
        height: 100%;
    }
    #stage{
        position:relative;
    }

    .cell{
        display: inline-block;
        width: 6vw;
        height: 6vw;
        border: 1px solid gray;
        background-color: white;
    }

</style>


<div class ="container">
    <div class = "row">
        <h1>Grid</h1>
        <div id="stage"></div>
    </div>
</div>
<script>
    var stage = document.querySelector("#stage");
    var pattern = [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    ]
    var SIZE = 60;
    var SPACE = 0;
    var ROWS =pattern.length;
    var COLUMNS = pattern[0].length;

    for(var row = 0; row < ROWS; row++)
    {
        for(var column = 0; column < COLUMNS; column++)
        {
            //Create a div HTML element called cell
            var cell = document.createElement("div");
            //Set its CSS class to "cell"
            cell.setAttribute("class", "cell");
            //Add the div HTML element to the stage
            stage.appendChild(cell);
            //Make it black if it's a "1"
            if(pattern[row][column] === 1)
            {
            cell.style.backgroundColor = "black";
            }
            //Position the cell in the correct place
            //with 10 pixels of space around it

        }
        document.write('<br>')
    }
</script>

The best way to do it is to separate your rendering and data.

In this case every time you update data you can trigger render. You can also trigger render function when something else happens for example screen resize.

Here is the pseudocode for your script. I'd wrap whole functionality to the object.

var grid = {
    pattern: [], // Initial pattern data
    setCell: function(x,y,val){
        // Make changes to the pattern then...
        // you can update the pattern representation so that it is always up to date
        this.render();
    },
    render: function() {
        // Clear previous render
        // Render it again based on current size of browser of device.
    }
};

grid.render();

window.onresize(function(){
    grid.render.call(grid); // this will trigger the grid refresh.
});

grid.setCell(1,1,5); // this will also trigger grid refresh

You can use flexbox like this:

Fiddle: http://jsfiddle.net/hb8njk27/

*, *::before, *::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

#stage {
  display: flex;
  flex-wrap: wrap;
}

.cell {
  flex: 0 1 6.6%;
  height: 60px;
  border: 1px solid gray;
  background-color: white;
}

This basically says, display: flex turns on flex. flex-wrap: wrap allows items to go on to multiple lines. flex on the cell class is shorthand for flex-grow , flex-shrink and flex-basis . So for flex-grow , do we want them to grow relative to other items? No. For flex-shrink do we want them to shrink relative to other items? Yes. And for flex-basis what is the length of the item? Well for 15 items per row thats roughly 6.6% of 100.

I also added box-sizing: border-box so that the width of your borders was included in the width and height of the element so that borders wouldn't throw off the percentages.

Then in your code I removed the two lines below this comment //Position the cell in the correct place since they are no longer needed.

And a final note, flex box is only supported in modern browsers. Which basically means everything except IE. There is no support in IE9 and down and partial support in IE10 and 11.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM