Cal-linux
Cal-linux

Reputation: 155

CSS-based layout equivalent of HTML-based table

I want a CSS solution (in principle HTML5/CSS3) that would reproduce the behaviour of the following table-based layout:

<table width="80%" align="center" border="1">
  <tr valign="top">
    <td>Some content that varies in size</td>
    <td width="200">Maybe an image, maybe some short text</td>
  </tr>
</table>

My best attempt with CSS gets me the left-side contents (the "content that varies in size" above) to wrap around the div on the right.

Here's what I'm trying:

div.outsidecontainer {
  position: relative;
  width: 80%;
  border: 1px solid silver;
  margin-left: auto;
  margin-right: auto;
}
div.absolute {
  float: right;
  width: 200px;
  margin-bottom: 1px;
  border: 1px solid silver;
}
div.filler {
  border: 1px solid silver;
  margin-bottom: 1px;
}
<div class="outsidecontainer">
  <div class="absolute">This is the fixed-size div on the right</div>
  <div class="filler">Another div element with a lot of text .....</div>
</div>

Any suggestions?

Upvotes: 2

Views: 975

Answers (2)

MikeM
MikeM

Reputation: 27405

a common pattern is to set the parent ("outsidecontainer" in this case) to position: relative then the child element ("absolute") to position: absolute and right: 0. This pattern set's a position: absolute child elements to be constrained to the boundaries of the parent element (rather than being constrained by default to boundaries of the 'body' element)

this is an alternative to float: right (which would also work)

then set margin-right to compensate for the width of the "absolute" div

div.outsidecontainer {
  position: relative;
  width: 80%;
  border: 1px solid red;
  margin-left: auto;
  margin-right: auto;
} 

div.absolute {
  position: absolute;
  right: 0; /* position to the right of "outsidecontainer" div */
  width: 200px;
  margin-bottom: 1px;
  border: 1px solid blue;
}

div.filler
{
  border: 1px solid black;
  margin-bottom: 1px;
  margin-right: 200px; /* compensate for "absolute" div's width */
}
<div class="outsidecontainer">
  <div class="absolute">
    <p>This is the fixed-size div on the right</p>
    <p>This is the fixed-size div on the right</p>
    <p>This is the fixed-size div on the right</p>
  </div>
  <div class="filler">
    <p>Another div element with a lot of text ..... </p>
    <p>Another div element with a lot of text ..... </p>
    <p>Another div element with a lot of text ..... </p>
    <p>Another div element with a lot of text ..... </p>
    <p>Another div element with a lot of text ..... </p>
    <p>Another div element with a lot of text ..... </p>
  </div>
</div>

Upvotes: 0

ZeroBased_IX
ZeroBased_IX

Reputation: 2727

You can acomplish this in a few ways.

Instead of using float right to get the content on the right, just place it on the right. With float: left; on each of the containers contents and placing a clearfix:both; in the bottom of the container: Your approach - fixed

* {
  box-sizing: border-box;
}

.outsidecontainer {
  width: 100%;
  border: 1px solid black;
}

.cell {
  float: left;
}

.absolute {
  width: 200px;
}

.filler {
  width: calc(100% - 200px);
  height: 100%;
}
/*used to stop the container from collapsing*/
.clearfix {
  clear: both;
}
<div class="outsidecontainer">
  <div class="filler cell">Another div element with a lot of text .....</div>
  <div class="absolute cell">This is the fixed-size div on the right</div>
  <div class="clearfix"></div>
</div>

Alternatively you can use the display: table to replicate a table using divs.

display: table Approach

.t-body {
  width: 80%;
  display: table;
}

.t-row {
  display: table-row;
}

.t-cell {
  display: table-cell;
  border: 1px solid black;
}

.fw {
  width: 200px;
}
<div class="t-body">
  <div class="t-row">
    <div class="t-cell">Another div element with a lot of text ....</div>
    <div class="t-cell fw">This is the fixed-size div on the right</div>
  </div>
</div>

Upvotes: 1

Related Questions