1

I wanted to make a little game with a div#field containing 100 div's with the shape of a square. I also want the div's to be responsive.

I tried to give them a width in percentage with css.

<style type="text/css">
    *{
        margin: 0;
        padding: 0;
    }
    div{
        border: 1px solid black;
        margin: auto;
        width: 10%;
    }
    #field > div{
        float: left;
        width: 10%;
    }
</style>

But it looked like:

float: left; Then I erased the float: left; and placed display: inline;

But it looked like:

display: inline; My next attempt to succeed was using jQuery to make to make my div's responsive, and my code looked like.

<!DOCTYPE html>
<html>
<head>
    <title>100 div's field</title>
    <meta charset="utf-8">
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        div{
            border: 1px solid black;
        }
        #field > div{
            float: left;
        }
    </style>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            for (var i = 0; i < 100; i++) {
                $('#field').append('<div></div>');
            };
            resizeWindow();
            $(window).resize(function(){
                resizeWindow();
            });
            function resizeWindow () {
                var windowHeight = $(window).height();
                var windowWidth = $(window).width();
                if(windowHeight < windowWidth){
                    var windowsize = windowHeight;
                }else{
                    var windowsize = windowWidth;
                }
                $('#field').css("width",  windowsize - windowsize * 0.1 + "px");
                $('#field').css("height", windowsize - windowsize * 0.1 + "px");
                $('#field > div').css("width",  windowsize * 0.1 - windowsize * 0.015 + "px");
                $('#field > div').css("height", windowsize * 0.1 - windowsize * 0.015 + "px");
            }
        });
    </script>
</head>
<body>
    <div id="field"></div>
</body>
</html>

I decreased the sizes with a 10th because I don't want the div's to be too big for my #field div. I thought my problem was solved now but, when I resize the browser window I had to many space in my #field div, or there wasn't enough space and my div's popped out.

large small

Also:

-Trying other browser didn't help.

-Is the only option to make a table?

-Or is it possible to add a lot of CSS Media Queries

call-me
  • 686
  • 9
  • 18
  • 2
    This is the sad reality of the accumulation of rounding errors. Also, see https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing because the 1+1px borders at each size also added to the 10% width/height. – biziclop Dec 29 '14 at 23:34
  • See: http://jsfiddle.net/vuyz8L4b/ – biziclop Dec 29 '14 at 23:45

5 Answers5

3

You should do it using pure CSS (no JS).

Instead of using float, you should just use display: inline-block, and use box-sizing: border-box to be free to add borders.

See an example here (I only used JS to add divs): http://jsfiddle.net/BaliBalo/auc40tmr/1/


To make the size of the field responsive to the size of the window while keeping the square aspect ratio, you can use either the vw or vh unit. This will be respectively a percentage of the window width / height. Doing it this way instead of using padding will make you able to insert content in the tiles.

Here is an updated example using vw : http://jsfiddle.net/BaliBalo/auc40tmr/3/


Another update to demonstrate that you can put text in squares using this method. This example also uses vmin (with a vm fallback for IE) to make the field take the maximum size available.

http://jsfiddle.net/BaliBalo/auc40tmr/5/

Bali Balo
  • 3,338
  • 1
  • 18
  • 35
  • Yes this is what I was hoping for, but I have never seen or heard about: "vw","vh" and "rem". Are they new in CSS3? – call-me Dec 30 '14 at 00:36
  • 1
    @call-me `vw` and `vh` are indeed CSS3 properties. They are [supported](http://caniuse.com/#feat=viewport-units) in every major browser (incuding IE 9+). You could also use `vmin` for min between `vw` and `vh` but in this case you should also add a `vm` fallback for IE. `rem` is also a CSS3 property and have approximatively the same [support](http://caniuse.com/#feat=rem). I like it a lot since it is dynamic as em, depending on the user default font-size, but you can rely on it even when messing with the parent font-size (as in my example). – Bali Balo Dec 30 '14 at 00:51
3

You can do this just fine with CSS. You need to use box-sizing: border-box though, so that the width of the border of each cell will be included in the 10% width. Otherwise, your cell's outerwidths are the widths of their contents, which are all 10% of the width of the container, plus the width of the border.

You should also use display: inline-block instead of float: left which more closely resembles your intent.

for (var i = 0; i < 100; ++i) {
  $('#container').append('<div></div>');
}
#container div {
  width: 10%;
  height: 10px;
  display: inline-block;
  border: 1px solid #000;
  box-sizing: border-box
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  
</div>
user229044
  • 232,980
  • 40
  • 330
  • 338
3

Use box-sizing: border-box to deal with the width calculation not accounting borders and display:inline-block so you do not have to worry about floats.

var html = Array.apply(null, new Array(100)).map(String.prototype.valueOf,"<div></div>");
document.getElementById("field").innerHTML = html.join("");
    *{
        margin: 0;
        padding: 0;
    }


    #field > div{
        box-sizing: border-box;
        display: inline-block;
        width: 10%;
        height: 20px;
        border: 1px solid black;
    }
<div id="field"></div>
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • Is all the code in the html var necessary? It seems complicated, what does it do? – call-me Dec 30 '14 at 00:05
  • 1
    It is a quick way to add 100 divs. Is it necessary? No; since your question is about CSS. It is just filling up the parent div without having to type 100 divs. Your way of appending 100 divs in a for loop is slower, but it works. What does it do? It creates an array with 100 entries and fills it with empty strings that is a div. It is just like doing `var x = []; for(var i=0;i<100; i++) { x.push("
    "); }`
    – epascarello Dec 30 '14 at 00:15
  • @espascarello `innerHTML` is actually quite slow since the browser has to parse the string content. It might be faster than using jQuery but the best way is definitely to append elements using native DOM methods (`createElement`, `appendChild`, ...), to a *not-yet-appended-to-body* parent element (to avoid repaints) then to append this parent to the page. – Bali Balo Dec 30 '14 at 01:21
2

try:

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

see also: Why did Bootstrap 3 switch to box-sizing: border-box?

Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
1

Fiddle: http://jsfiddle.net/7zL0L359/4/

  • Use float: left; otherwise you'll get to deal with margin/padding issues.
  • Set box-sizing: border-box; on items, otherwise your border-width will get in the way.
  • Use arrays to push and then join items, this is much faster. And you'll need your game to perform! :)
  • Important: use padding-bottom: 10%; on items instead of fixes size height. This way you'll get squares no matter what height your parent container is.

HTML:

<div id="field"></div>

JS + jQuery:

$(document).ready(function() {
  var $field = $('#field');
  var boxes = [];
  for (var i = 0; i < 100; i++) {
    boxes.push('<div class="item"></div>');
  };
  $field.append(boxes.join(''));
});

CSS:

#field {
    width: 100%;
}
.item {
    float: left;
    width: 10%;
    padding-bottom: 10%;

    box-sizing: border-box;
    border: 1px solid black;
}