I need to create a 3-column layout where the center column is twice the width of the side columns, without using bootstrap, since bootstrap doesn't work in emails.
In bootstrap, it would be:
<div class="container">
<div class="col-3">
</div>
<div class="col-6">
<!-- All page content goes here -->
</div>
<div class="col-3">
</div>
</div>
How can I achieve this without using bootstrap?
Note
I found this code:
<div class="row">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
But that didn't seem to work.
For emails you need tables:
table {
width:100%;
table-layout:fixed;
border-spacing:0;
}
td {
width:25%;
}
td:nth-child(2) {
width:50%;
}
.column {
padding:15px;
border:1px solid;
}
<table class="row">
<tr>
<td class="column"></td>
<td class="column"></td>
<td class="column"></td>
</tr>
</table>
Especially for emails the simplest solutions are the best, so I'd recommended to use table with inline styles, like this:
table {
width: 600px;
}
td {
border: 1px solid #000;
}
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td style="width: 25%; height: 20px;"></td>
<td style="width: 50%; height: 20px;"></td>
<td style="width: 25%; height: 20px;"></td>
</tr>
</tbody>
</table>
I am not sure in what sense the given example didn't work as this snippet gives columns of widths 25%, 50%, 25% as required in the question.
However, note that some email systems may not support CSS other than an inline style so in the snippet the styles have been put inline and padding etc removed as you will have to decide what to do about that and compensate in the width definitions. It may still be that email systems do not accept HTML even just with inline CSS but it depends on your exact use case whether this matters and how you will ensure the info is presented OK to the user if it is ignored.
<div>
<div style=" background-color:#aaa; width: 25%; float: left;">
<h2>Column 1</h2>
<p>Some text..</p>
</div>
<div style=" background-color:#bbb; width: 50%; float: left;">
<h2>Column 2</h2>
<p>Some text..</p>
</div>
<div style=" background-color:#ccc; width: 25%; float: left;">
<h2>Column 3</h2>
<p>Some text..</p>
</div>
</div>
As I wrote in the comment above, today, you can only use table display for emails. Flex and Grid will not work!
There is one more very important point. Template for emails does not have access to CSS, so all styles must be specified inside tags.
I made you a simple template for emails with content. Just use it. If you need to fix or modify something, then let me know.
<table style="width: 100%; border: 1px solid black">
<tr>
<th style="width: 25%; border:1px solid black">title 1</th>
<th style="width: 50%; border:1px solid black">title 2</th>
<th style="width: 25%; border:1px solid black">title 3</th>
</tr>
<tr>
<td style="border:1px solid black">content 1</td>
<td style="border:1px solid black">content 2</td>
<td style="border:1px solid black">content 3</td>
</tr>
</table>
Use inline-styles:
<div style="display: flex;">
<div style="flex: 25%; max-width: 25%">
column 1
</div>
<div style="flex: 50%; max-width: 50%">
column 2
</div>
<div style="flex: 25%; max-width: 25%">
column 3
</div>
</div>
.row{
display:flex;
height:150px;
border:2px solid red;
}
.column{
border:1px solid green;
margin:2px;
width:30%;
}
.column1, .column3{
flex-grow:1;
}
.column2{
flex-grow:2;
}
<div class="row">
<div class="column"></div>
<div class="column2 column"></div>
<div class="column"></div>
</div>
The flex grow should be a very quick solution for you. Run the code to see how it works.
The second bit of code you posted doesn't work because you haven't defined the row or column CSS classes.
You have a two main options:
Use the bootstrap classes by copying their code into a style tag in your email body.
Write your own classes to achieve this layout. Here's an example using display: flex.
.row {
height: 100vh;
width: 100vw;
display: flex;
}
#col1 {
height: 100vh;
flex-basis: 20%;
background-color: red;
}
#col2 {
height: 100vh;
flex-basis: 60%;
background-color: green;
}
#col3 {
height: 100vh;
flex-basis: 20%;
background-color: blue;
}
<div class="row">
<div id="col1"></div>
<div id="col2"></div>
<div id="col3"></div>
</div>
UPDATE:
For Emails, Tables will work for sure :) Yup you need to go for tables only. Because some email systems don't support external CSS.
litmus.com
.table{
width:100%;
}
tr td{
width:25%;
height:50px;
}
tr .second{
width:50%;
}
<table class="table" border="1" cellspacing="0" cellpadding="0">
<tr>
<td></td>
<td class="second"></td>
<td></td>
</tr>
</table>
Here is a cell with two blocks, inside it is a <textarea> and a <div>.
<table style="width:100%; border:solid 1px">
<tr>
<td style="width:70%">
<textarea rows="9" style="background-color:#ee9; width:100%;"></textarea>
</td>
<td style="width:30%">
<div style=" width:100%; height:100%; background-color:#eaa; border:solid 1px;"></div>
</td>
</tr>
</table>
How can I make these completely fit inside the table by a 70:30 ratio?
flex is a better option :
body >div{
display:flex;
}
body >div textarea {
flex:7;
margin:2px;
}
body >div > div {
flex:3;
margin:2px;
}
<div>
<textarea rows="9" style="background-color:#ee9;"></textarea>
<div style="background-color:#eaa; border:solid 1px;"></div>
</div>
grid is too
body>div {
display: grid;
grid-template-columns: 7fr 3fr;
grid-gap:4px
}
<div>
<textarea rows="9" style="background-color:#ee9;"></textarea>
<div style="background-color:#eaa; border:solid 1px;"></div>
</div>
It's better to use grid layout to make this thing as follows.
.main {
display: grid;
grid-template-columns: 70% 30%;
width: 100%;
}
<div class="main">
<textarea rows="9" style="background-color:#ee9; width:100%;"></textarea>
<div style=" width:100%; height:100%; background-color:#eaa; border:solid 1px;"></div>
</div>
You can use css flex-basis property
<div style="display:flex;width: 300px;height: 100px;border: 1px solid #c3c3c3;">
<div style="flex-basis: 70%;padding:0;background:yellow"></div>
<div style="flex-basis: 30%;padding:0;background:red"></div>
</div>
I'm trying to construct a layout similar to the following:
+---+---+---+
| | | |
+---+---+---+
| |
+-----------+
where the bottom is filling the space of the upper row.
If this were an actual table, I could easily accomplish this with <td colspan="3">, but as I'm simply creating a table-like layout, I cannot use <table> tags. Is this possible using CSS?
There's no simple, elegant CSS analog for colspan.
Searches on this very issue will return a variety of solutions that include a bevy of alternatives, including absolute positioning, sizing, along with a similar variety of browser- and circumstance-specific caveats. Read, and make the best informed decision you can based on what you find.
There is no colspan in css as far as I know, but there will be column-span for multi column layout in the near future, but since it is only a draft in CSS3, you can check it in here. Anyway you can do a workaround using div and span with table-like display like this.
This would be the HTML:
<div class="table">
<div class="row">
<span class="cell red first"></span>
<span class="cell blue fill"></span>
<span class="cell green last"></span>
</div>
</div>
<div class="table">
<div class="row">
<span class="cell black"></span>
</div>
</div>
And this would be the css:
/* this is to reproduce table-like structure
for the sake of table-less layout. */
.table { display:table; table-layout:fixed; width:100px; }
.row { display:table-row; height:10px; }
.cell { display:table-cell; }
/* this is where the colspan tricks works. */
span { width:100%; }
/* below is for visual recognition test purposes only. */
.red { background:red; }
.blue { background:blue; }
.green { background:green; }
.black { background:black; }
/* this is the benefit of using table display, it is able
to set the width of it's child object to fill the rest of
the parent width as in table */
.first { width: 20px; }
.last { width: 30px; }
.fill { width: 100%; }
The only reason to use this trick is to gain the benefit of table-layout behaviour, I use it alot if only setting div and span width to certain percentage didn't fullfil our design requirement.
But if you don't need to benefit from the table-layout behaviour, then durilai's answer would suit you enough.
Another suggestion is using flexbox instead of tables altogether. This is a "modern browser" thing of course, but come on, it's 2016 ;)
At least this might be an alternative solution for those looking for an answer to this nowadays, since the original post was from 2010.
Here's a great guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.table {
border: 1px solid red;
padding: 2px;
max-width: 300px;
display: flex;
flex-flow: row wrap;
}
.table-cell {
border: 1px solid blue;
flex: 1 30%;
}
.colspan-3 {
border: 1px solid green;
flex: 1 100%;
}
<div class="table">
<div class="table-cell">
row 1 - cell 1
</div>
<div class="table-cell">
row 1 - cell 2
</div>
<div class="table-cell">
row 1 - cell 3
</div>
<div class="table-cell colspan-3">
row 2 - cell 1 (spans 3 columns)
</div>
</div>
<div style="width: 100%;">
<div style="float: left; width: 33%;">Row 1 - Cell 1</div>
<div style="float: left; width: 34%;">Row 1 - Cell 2</div>
<div style="float: left; width: 33%;">Row 1 - Cell 3</div>
</div>
<div style="clear: left; width: 100%;">
Row 2 - Cell 1
</div>
To provide an up-to-date answer: The best way to do this today is to use css grid layout like this:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"top-left top-middle top-right"
"bottom bottom bottom"
}
.item-a {
grid-area: top-left;
}
.item-b {
grid-area: top-middle;
}
.item-c {
grid-area: top-right;
}
.item-d {
grid-area: bottom;
}
and the HTML
<div class="container">
<div class="item-a">1</div>
<div class="item-b">2</div>
<div class="item-c">3</div>
<div class="item-d">123</div>
</div>
That isn't part of the purview of CSS. colspan describes the structure of the page's content, or gives some meaning to the data in the table, which is HTML's job.
I've had some success, although it relies on a few properties to work:
table-layout: fixed
border-collapse: separate
and cell 'widths' that divide/span easily, i.e. 4 x cells of 25% width:
.div-table-cell,
* {
box-sizing: border-box;
}
.div-table {
display: table;
border: solid 1px #ccc;
border-left: none;
border-bottom: none;
table-layout: fixed;
margin: 10px auto;
width: 50%;
border-collapse: separate;
background: #eee;
}
.div-table-row {
display: table-row;
}
.div-table-cell {
display: table-cell;
padding: 15px;
border-left: solid 1px #ccc;
border-bottom: solid 1px #ccc;
text-align: center;
background: #ddd;
}
.colspan-3 {
width: 300%;
display: table;
background: #eee;
}
.row-1 .div-table-cell:before {
content: "row 1: ";
}
.row-2 .div-table-cell:before {
content: "row 2: ";
}
.row-3 .div-table-cell:before {
content: "row 3: ";
font-weight: bold;
}
.div-table-row-at-the-top {
display: table-header-group;
}
<div class="div-table">
<div class="div-table-row row-1">
<div class="div-table-cell">Cell 1</div>
<div class="div-table-cell">Cell 2</div>
<div class="div-table-cell">Cell 3</div>
</div>
<div class="div-table-row row-2">
<div class="div-table-cell colspan-3">
Cor blimey he's only gone and done it.
</div>
</div>
<div class="div-table-row row-3">
<div class="div-table-cell">Cell 1</div>
<div class="div-table-cell">Cell 2</div>
<div class="div-table-cell">Cell 3</div>
</div>
</div>
https://jsfiddle.net/sfjw26rb/2/
Also, applying display:table-header-group or table-footer-group is a handy way of jumping 'row' elements to the top/bottom of the 'table'.
You could trying using a grid system like http://960.gs/
Your code would be something like this, assuming you're using a "12 column" layout:
<div class="container_12">
<div class="grid_4">1</div><div class="grid_4">2</div><div class="grid_4">3</div>
<div class="clear"></div>
<div class="grid_12">123</div>
</div>
Try adding display: table-cell; width: 1%; to your table cell element.
.table-cell {
display: table-cell;
width: 1%;
padding: 4px;
border: 1px solid #efefef;
}
<div class="table">
<div class="table-cell">one</div>
<div class="table-cell">two</div>
<div class="table-cell">three</div>
<div class="table-cell">four</div>
</div>
<div class="table">
<div class="table-cell">one</div>
<div class="table-cell">two</div>
<div class="table-cell">three</div>
<div class="table-cell">four</div>
</div>
<div class="table">
<div class="table-cell">one</div>
</div>
The CSS properties "column-count", "column-gap", and "column-span" can do this in a way that keeps all the columns of the pseudo-table inside the same wrapper (HTML stays nice and neat).
The only caveats are that you can only define 1 column or all columns, and column-span doesn't yet work in Firefox, so some additional CSS is necessary to ensure it will displays correctly.
https://www.w3schools.com/css/css3_multiple_columns.asp
.split-me {
-webkit-column-count: 3;
-webkit-column-gap: 0;
-moz-column-count: 3;
-moz-column-gap: 0;
column-count: 3;
column-gap: 0;
}
.cols {
/* column-span is 1 by default */
column-span: 1;
}
div.three-span {
column-span: all !important;
}
/* alternate style for column-span in Firefox */
#-moz-document url-prefix(){
.three-span {
position: absolute;
left: 8px;
right: 8px;
top: auto;
width: auto;
}
}
<p>The column width stays fully dynamic, just like flex-box, evenly scaling on resize.</p>
<div class='split-me'>
<div class='col-1 cols'>Text inside Column 1 div.</div>
<div class='col-2 cols'>Text inside Column 2 div.</div>
<div class='col-3 cols'>Text inside Column 3 div.</div>
<div class='three-span'>Text div spanning 3 columns.</div>
</div>
<style>
/* Non-Essential Visual Styles */
html * { font-size: 12pt; font-family: Arial; text-align: center; }
.split-me>* { padding: 5px; }
.cols { border: 2px dashed black; border-left: none; }
.col-1 { background-color: #ddffff; border-left: 2px dashed black; }
.col-2 { background-color: #ffddff; }
.col-3 { background-color: #ffffdd; }
.three-span {
border: 2px dashed black; border-top: none;
text-align: center; background-color: #ddffdd;
}
</style>
if you use div and span it will occupy more code size when the datagrid-table row are more in volume. This below code is checked in all browsers
HTML:
<div id="gridheading">
<h4>Sl.No</h4><h4 class="big">Name</h4><h4>Location</h4><h4>column</h4><h4>column</h4><h4>column</h4><h4>Amount(Rs)</h4><h4>View</h4><h4>Edit</h4><h4>Delete</h4>
</div>
<div class="data">
<h4>01</h4><h4 class="big">test</h4><h4>TVM</h4><h4>A</h4><h4>I</h4><h4>4575</h4><h4>4575</h4></div>
<div class="data">
<h4>01</h4><h4 class="big">test</h4><h4>TVM</h4><h4>A</h4><h4>I</h4><h4>4575</h4><h4>4575</h4></div>
CSS:
#gridheading {
background: #ccc;
border-bottom: 1px dotted #BBBBBB;
font-size: 12px;
line-height: 30px;
text-transform: capitalize;
}
.data {
border-bottom: 1px dotted #BBBBBB;
display: block;
font-weight: normal;
line-height: 20px;
text-align: left;
word-wrap: break-word;
}
h4 {
border-right: thin dotted #000000;
display: table-cell;
margin-right: 100px;
text-align: center;
width: 100px;
word-wrap: break-word;
}
.data .big {
margin-right: 150px;
width: 200px;
}
If you come here because you have to turn on or off the colspan attribute (say for a mobile layout):
Duplicate the <td>s and only show the ones with the desired colspan:
table.colspan--on td.single {
display: none;
}
table.colspan--off td.both {
display: none;
}
<!-- simple table -->
<table class="colspan--on">
<thead>
<th>col 1</th>
<th>col 2</th>
</thead>
<tbody>
<tr>
<!-- normal row -->
<td>a</td>
<td>b</td>
</tr>
<tr>
<!-- the <td> spanning both columns -->
<td class="both" colspan="2">both</td>
<!-- the two single-column <td>s -->
<td class="single">A</td>
<td class="single">B</td>
</tr>
<tr>
<!-- normal row -->
<td>a</td>
<td>b</td>
</tr>
</tbody>
</table>
<!--
that's all
-->
<!--
stuff only needed for making this interactive example looking good:
-->
<br><br>
<button onclick="toggle()">Toggle colspan</button>
<script>/*toggle classes*/var tableClasses = document.querySelector('table').classList;
function toggle() {
tableClasses.toggle('colspan--on');
tableClasses.toggle('colspan--off');
}
</script>
<style>/* some not-needed styles to make this example more appealing */
td {text-align: center;}
table, td, th {border-collapse: collapse; border: 1px solid black;}</style>
I came here because currently the WordPress table block doesn't support the colspan parameter and i thought i will replace it using CSS. This was my solution, assuming that the columns are the same width:
table {
width: 100%;
}
table td {
width: 50%;
background: #dbdbdb;
text-align: center;
}
table tr:nth-child(2n+1) {
position:relative;
display:block;
height:20px;
background:green;
}
table tr:nth-child(2n+1) td {
position:absolute;
left:0;
right:-100%;
width: auto;
top:0;
bottom:0;
background:red;
text-align:center;
}
<table>
<tr>
<td>row</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
<tr>
<td>row</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
</table>
You could always position:absolute; things and specify widths. It's not a very fluid way of doing it, but it would work.
I've created this fiddle:
http://jsfiddle.net/wo40ev18/3/
HTML
<div id="table">
<div class="caption">
Center Caption
</div>
<div class="group">
<div class="row">
<div class="cell">Link 1t</div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell ">Link 2</div>
</div>
</div>
CSS
#table {
display:table;
}
.group {display: table-row-group; }
.row {
display:table-row;
height: 80px;
line-height: 80px;
}
.cell {
display:table-cell;
width:1%;
text-align: center;
border:1px solid grey;
height: 80px
line-height: 80px;
}
.caption {
border:1px solid red; caption-side: top; display: table-caption; text-align: center;
position: relative;
top: 80px;
height: 80px;
height: 80px;
line-height: 80px;
}
Media Query classes can be used to achieve something passable with duplicate markup. Here's my approach with bootstrap:
<tr class="total">
<td colspan="1" class="visible-xs"></td>
<td colspan="5" class="hidden-xs"></td>
<td class="focus">Total</td>
<td class="focus" colspan="2"><%= number_to_currency #cart.total %></td>
</tr>
colspan 1 for mobile, colspan 5 for others with CSS doing the work.
How can I make a table in css/html like this:
I want to use only div, not <table> tags.
Code, yet:
<style>
.tab_in {
display: table-cell;
border: 1px dotted red;
padding: 4px 6px;
}
</style>
<div style="text-align:center;">
<div class="tab_in">
<div>a</div>
<div>b</div>
</div>
<div class="tab_in" style="vertical-align:middle;">c</div>
<div class="tab_in" style="vertical-align:middle;">d</div>
<div class="tab_in" style="vertical-align:middle;">e</div>
</div>
Use fluid grid system which uses percents instead of pixels for column widths. and handle the external width of it using a external container.
You can do something like:
JSFiddle Demo
HTML:
<div class="box">
<div class="row-fluid show-grid">
<div class="span4">
<div class="rowspan2">
<span class="valign-helper"></span>
a
</div>
<div class="rowspan2">
<span class="valign-helper"></span>
b
</div>
</div>
<div class="span4">
<div>c</div>
<div>d</div>
<div>e</div>
<div>f</div>
</div>
<div class="span4">
<div>g</div>
<div>h</div>
<div>i</div>
<div>j</div>
</div>
</div>
</div>
Note: to vertically align text you can also do using "display: table-cell" css property to the class 'rowspan2'. and remove the tag with class "valign-helper"
CSS:
body {
margin: 50px;
}
.box {
width:500px;
padding: 0 10px;
background-color: #000;
}
.show-grid [class*="span"] div {
background-color: #fff;
text-align: center;
min-height: 40px;
line-height: 40px;
margin-left: 0;
margin-top: 10px;
margin-bottom: 10px;
}
.show-grid [class*="span"] .rowspan2 {
height: 90px;
margin-bottom: 0;
}
.valign-helper {
display: inline-block;
height: 100%;
vertical-align: middle;
}
Here's an example of one way you might accomplish this:
http://jsfiddle.net/mori57/cDEGw/1/
html:
<table class="tab_out">
<tr>
<td rowspan="0" class="col">
<div class="tab_in">a</div>
<div class="tab_in">b</div>
</td>
<td><div class="tab_in">c</div></td>
<td><div class="tab_in">g</div></td>
</tr>
<tr>
<td><div class="tab_in">d</div></td>
<td><div class="tab_in">h</div></td>
</tr>
<tr>
<td><div class="tab_in">e</div></td>
<td><div class="tab_in">i</div></td>
</tr>
<tr>
<td><div class="tab_in">f</div></td>
<td><div class="tab_in">j</div></td>
</tr>
</table>
CSS:
.tab_out {
width: 800px;
margin-bottom: 20px;
text-align:center;
}
.tab_out td {
border:1px dotted red;
padding: 4px 6px;
margin-bottom: 0;
vertical-align:middle;
}
.tab_in {
display: block;
border: 1px dotted green;
}
Is this any closer to what you're looking for? I really don't see an efficient way to accomplish your layout without using a table, at this point. Mind you, the div inside each TD is optional, I just used it to show you where the element actually appears inside the table.
The image basically shows what is happening. I have a wrapper of 1270px. Inside that wrapper (indicated by the vert line on the right) I have 4 divs and one table. The table contents is pushing past the page wrapper. THe page wrapper does not have a float as it is only to center the content on the page.
I have tried the following but nothing works:
border: none;
padding: 0px;
border-collapse: collapse;
overflow: hidden;
table-layout: fixed;
What is causing this? This is also allowing all the other content from the other 4 divs to push past the page wrapper as well.
EDIT:
<div id="wrap-page">
<div id="wrap-content">
<table id="content">
<tbody>
<tr>
<td id="featured">
<h1>h1</h1>
<p>Lorem ipsum</p>
<h2>h2</h2>
<p>Lorem ipsum</p>
</td>
<td class="sidebar">
<p>Lorem ipsum</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
html, body{
width:100%;
margin:0;
padding:0;
background:#ccc;
font-size:100%;
line-height:1;
font-family:Arial;
}
#wrap-page{
float:left;
margin:auto;
width:1270px;
}
#wrap-content{
margin:0 5px;
border:1px solid;
}
#content{
position:relative;
float:left;
border-collapse:collapse;
width:1270px;
margin:7px 0;
}
#featured{
width:822px;
}
.sidebar{
width:193px;
vertical-align:top;
}
Your inner divs widths and table is greater than your outer wrapper of 1270px.
It looks like you are just trying to add a border to your text...
Please try this alternative (without tables):
http://jsfiddle.net/UXKTA/9/
.test
{
padding: 5px;
border: 1px solid black;
width: 200px;
}