Stark_kids
Stark_kids

Reputation: 547

Drawing complex grid with Bootstrap

I'm working with a HTML view using Bootstrap3. I need to create a template with different cells and I usually work with cols and rows, but this time I have a problem with drawing one column.

This is the scheme I need:

This is the code:

<div class="row">
  <div class="col-md-3 doubleHeight"></div>
  <div class="col-md-9 singleHeight"></div>
  <div class="col-md-3 singleHeight"></div>
  <div class="col-md-3 singleHeight"></div>
  <!--column bottom right-->
  <!--column bottom left-->
</div>

The problem begins when I try to draw the column on the bottom right. If I draw it after the two col-md-3, it doesn't allow me to show the last column on the left inline with it. If I draw it after the last column on the left, it doesn't occupy the space above. Have you got any idea of the possible solution? Thanks.

Upvotes: 4

Views: 1267

Answers (3)

Stark_kids
Stark_kids

Reputation: 547

In this case the problem was simplified because I had divs with fixed height. I kept Bootstrap template and I assigned to the bottom left div the class of col-md-9, giving it a certain amount of space from the top. I know it's not the best way to do it, but it is horizontally responsive still.

This is the HTML code:

<div class="row-fluid">
<div class="col-md-12">
    <div class="row">

        <div class="col-md-3 doubleRow box">...</div>
        <div class="col-md-9 singleRow box">...</div>
        <div class="col-md-3 singleRow box">...</div>
        <div class="col-md-3 singleRow box">...</div>
        <div class="col-md-9 singleRow box">...</div>
        <div class="col-md-3 doubleRow box upper">...</div>
    </div>
</div>

And this is the CSS:

.singleRow{
    height:280px;
}

.doubleRow{
    height:560px;
    max-height:100%;
}

.upper{
    top: -280px;
    margin-bottom: -280px;  
}

.box {          
    border-style: solid;
    border-width: 5px;
    border-color:black;
    text-align: center;
    padding: 1%;
    position: relative;
}

Upvotes: 0

Christopher Esbrandt
Christopher Esbrandt

Reputation: 1198

WARNING: This post contains multiple variations of the same snippet between explanations to demonstrate the logic and provide a visual representation of how the code will actually operate. If you edit it, please keep that in mind.

Before I give you the solution, I want to make something PERFECTLY clear, this is NOT supported by the Bootstrap framework. To clarify, Bootstrap supports the wrapping of the blocks which can be used to account for this, however, it does NOT manipulate the height to accommodate a block spanning multiple rows.

Alright, with that said, the closet you can get to your request is via column wrapping. You can't do multiple layers of blocks because you have blocks that would belong to two different parents, and that simply isn't possible to quantify with the current CSS/HTML structure. Further, you can't do anything for the last block to appear next to the bottom-right block.

Here's a little demo of the structure that gets closet to what you are asking for:

div div {
    border: 1px solid black;
}
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and unknown rows.</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
</div>

I added a little border to give a visual idea of how it actually renders. Here's the downside to this, it is 100% dependent upon your control of the content in each block to maintain the rows. For example, if you put only enough content in the very first block to account for the height of the second block, you will get the third, fourth, and fifth blocks left flushed and push the sixth block down further.

div div {
    border: 1px solid black;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<div class="row">
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">One liner</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner<br />Two liner</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">One liner</div>
</div>

I'm afraid that there is not "easy" way to mitigate this, short of defining height for each block. Further, the bottom-right block can NEVER exceed the content height of the third and fourth blocks. If it exceeds it, then you get a gap between the sixth block and those immediately above it.

div div {
    border: 1px solid black;
}

.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
    height: 50px;
}

.row-2 {
    height: 100px;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<div class="row">
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 row-2">This block spans one column and unknown rows.</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
    <div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 row-2">This block spans one column and row.</div>
    <div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
</div>

Even though the sixth block fits into the gap, it can only follow the structure if it is after the fifth block. This forces the browser to render it below it. That's block for you.

Honestly, the ONLY way to make that layout in any framework of HTML(5) and CSS(3) is to use a table. It's a HIGHLY discouraged practice for layouts, but it, truthfully, is the only option that I know of.

Here's the upside, you can still use the Bootstrap col-lg-*, col-md-*, col-sm-*, and col-xs-* classes on the tds to ensure they follow the Bootstrap columns sizing.

td {
    border: 1px solid black;
    vertical-align: top;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<table>
    <tr>
        <td rowspan="2">This block spans one column and two rows.</td>
        <td colspan="3">This block spans three columns and one row.</td>
    </tr>
    <tr>
        <td>This block spans one column and row.</td>
        <td>This block spans one column and row.</td>
        <td rowspan="2">This block spans one column and two rows.</td>
    </tr>
    <tr>
        <td colspan="3">This block spans three columns and one row.</td>
    </tr>
</table>

I'm sorry, I know it's not quite what you were looking for, but, at least as far as my knowledge is concerned, it simply isn't possible to do that a wraparound layout without a table.

Upvotes: 3

Toby
Toby

Reputation: 13385

Masonry (javascript) seems ideal for this, although not pure CSS/Bootstrap.

Upvotes: 0

Related Questions