Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Layout with CSS (or should I give up and use tables?)

Tags:

html

css

I am trying to achieve the following Layout, as per screenshot.

Layout using tables

Main features are

  • Screen divided into 3 regions (columns);
  • Left / Right columns are fixed width;
  • Middle column expands as per Browser width
  • Right column is subdivided into two regions
  • Bottom region is fixed size, always at the bottom
  • Top region expands as per Browser height

Using HTML-tables took me about 2 hours to generate the above screenshot, with the above features.

After stuffing around with CSS for two days, I cannot get it looking as above, my attempt at CSS and associated screenshot follow below:

<html> 
<head> 
    <title>My Layout</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css"> 
    body{
        height:100%;
        background:beige;
    }

    #header { 
        width:100%;
        height:60px;
        text-align:center;
        background:#A7C942; 
        color:#fff;
        float:left; 
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        font-size:2em;
    } 

    #leftDiv { 
        float:left; 
        width:150px;
        height:90%;
        background:aquamarine; 
    } 
    #midDiv { 
        float:left; 
        width:auto; 
        height:90%;
        background:lightsalmon; 
        display:block;
    } 
    #rightDiv { 
        float:right; 
        width:365px; 
        height:90%;
        background:green; 
        display:block;
    }


    #topRow {
        background-color:lightgoldenrodyellow;
    }

    #bottomRow {
        background-color:lightpink;
        height:200px;
    }
    </style> 
</head> 

<body> 
<div id="body"> 
    <div id="main"> 
        <div id="header">my header</div>

        <div id="leftDiv">
            <p>LEFT</p>
        </div> 

        <div id="midDiv">
            <p>MIDDLE</p>
        </div> 

        <div id="rightDiv">
            <p>RIGHT</p>
            <div id="topRow">
                TOP
            </div>
            <div id="bottomRow">
                BOTTOM
            </div>
        </div>
    </div> 
</div> 
</body> 
</html>

Screenshot with CSS: Layout using CSS

Problems with the CSS attempt are:

  • Middle col does not expand (salmon colored part);
  • instead white color appears out of nowhere;
  • cannot get pink region to stay at the bottom always
  • Cannot get yellow region to stretch up and down
  • unwanted wrapping (i.e. the right region goes under left, middle regions)

Therefore, I am about to unleash my solution using tables, unless some die-hard CSS fanatic comes to the rescue with a working answer:-)

Update Great answers, at the time of this update there were 4. I tried out all 4 on Firefox and Chrome, and every answer is acceptable. But i can only choose one as the accepted answer, and i will go with the one that's plain and simple using only css and absolute positioning (no flexbox nor css-tables).

Thank you muchly to @matthewelsom, @Pangloss, @Shrinivas, @Paulie_D; I am sure anyone who stumbles upon your answers will find it useful for their use case. Upvotes for everyone, your efforts are appreciated!

like image 819
joedotnot Avatar asked Jul 01 '15 15:07

joedotnot


2 Answers

Check out this fiddle.

It uses basic CSS and HTML and NO framework.

The key elements which allows this type of positioning are these css properties: left, right, top, bottom.

The demo uses these properties.

Here is the snippet.

body {
  background: beige;
  margin: 0;
}
#header {
  width: 100%;
  height: 60px;
  text-align: center;
  background: #A7C942;
  color: #fff;
  font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  font-size: 2em;
}
#leftDiv {
  position: absolute;
  float: left;
  width: 150px;
  top: 60px;
  bottom: 0;
  background: aquamarine;
}
#midDiv {
  position: absolute;
  float: left;
  top: 60px;
  bottom: 0;
  left: 150px;
  right: 365px;
  min-width: 50px;
  background: lightsalmon;
}
#rightDiv {
  position: absolute;
  float: right;
  width: 365px;
  top: 60px;
  bottom: 0;
  right: 0;
  background: green;
}
#topRow {
  position: absolute;
  width: 100%;
  top: 0;
  bottom: 50px;
  min-height: 20px;
  background-color: lightgoldenrodyellow;
}
#bottomRow {
  position: absolute;
  background-color: lightpink;
  width: 100%;
  height: 50px;
  bottom: 0;
}
<div id="body">
  <div id="main">
    <div id="header">my header</div>
    <div id="leftDiv">
      <p>LEFT</p>
    </div>
    <div id="midDiv">
      <p>MIDDLE</p>
    </div>
    <div id="rightDiv">
      <div id="topRow">TOP</div>
      <div id="bottomRow">BOTTOM</div>
    </div>
  </div>
</div>
like image 197
Shrinivas Shukla Avatar answered Oct 01 '22 00:10

Shrinivas Shukla


Here is a quick flex layout, very rough but you'll get the idea. You can read more about Flexbox on CSS tricks.

I have also made the design responsive so the layout will fill 100% width on screens under 480px width.

CODEPEN HERE

html, body {
  height: 100%;
  padding: 0;
  margin: 0;
}
.wrapper {
  height: 100%;
  display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
  display: -webkit-box;  /* OLD - iOS 6-, Safari 3.1-6, BB7 */
  display: -ms-flexbox;  /* TWEENER - IE 10 */
  display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
  
  -webkit-flex-direction: column;
  flex-direction: column;
}

.wrapper > * {
   flex: 1 100%;
  -webkit-flex: 1 100%; 
}

.header {
  flex: 1;
  -webkit-flex: 1; 
  
  background: green;
  width: 100%;
  max-height: 80px;
}

.below {
  flex: 1;
  -webkit-flex: 1; 
  
  display: flex;        
  display: -webkit-box;  
  display: -ms-flexbox; 
  display: -webkit-flex;  
  
  -webkit-flex-direction: row;
  flex-direction: row;
}

.main {
  background: deepskyblue;
  flex: 3 0px;
  -webkit-flex: 3 0px;
  
  -webkit-order: 2;
  order: 2;
}

.left {
  background: yellow;
  max-width: 100px;
  flex: 1 auto;
  -webkit-flex: 1 auto;
  
  -webkit-order: 1;
  order: 1;
}

.right {
  background: hotpink;
  max-width: 300px;
  position: relative;
  
  display: flex;        
  display: -webkit-box;  
  display: -ms-flexbox; 
  display: -webkit-flex;  
  
  flex: 1 auto;
  -webkit-flex: 1 auto;
  
  -webkit-order: 3;
  order: 3;
  
  -webkit-flex-direction: column;
  flex-direction: column;
}
.top {
  background: lightpink;
  
  flex: 1 auto;
  -webkit-flex: 1 auto;
}
.bottom {
  background: salmon;
  max-height: 200px;
  width: 100%;
  
  flex: 1 auto;
  -webkit-flex: 1 auto;
}
@media screen and (max-width: 479px) {
  .below {
    -webkit-flex-direction: column;
    flex-direction: column;
  }
  .left, .right, .main {
    max-width: 100%;
    
    flex: 1;
    -webkit-flex: 1;
  }
  body, html, .wrapper {
    height: auto;
  }
}
<div class="wrapper">
  <header class="header"><h3>Header</h3><p>Fixed height 80px, 100% width</p></header>
  <div class="below">
    <article class="main">
    <h3>Flexible width Article</h3>
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo.</p>
  </article>
    <aside class="left">
      <h3>Left</h3>
      <p>100px fixed width</p>
    </aside>
    <aside class="right">
    <div class="top">
      <h3>Right Top</h3>
      <p>Flexible Height, Fixed width 300px</p>
    </div>
    <div class="bottom">
      <h3>Right Bottom</h3>
      <p>Fixed width 300px, Fixed Height 200px</p>
    </div>
  </aside>
  </div>
</div>
like image 29
matthewelsom Avatar answered Oct 01 '22 00:10

matthewelsom