How (and why) to use display: table-cell (CSS) - html

I have a site with a very active background (I'm talking 6 or so different z-indexes here 2 with animations). I wanted a in the foreground that had content but wanted a "window" through to the background in it. Some problems I had:
you can't "punch a hole" in a background, so...
I built a containing div, lets call it "srminfo"
Inside that I had a "top", "left", "window", "right" and "bottom"
the top, left, right, bottom all had opaque white backgrounds
while the srminfo and window divs had background:none;
No matter how hard I tried, the "right" div wouldn't fill the space between the "top" and "bottom" divs, I tried a lot of different things. The reason it had to be dynamic is that the text in the "left" div was dynamic based on the background colour, which was itself generated randomly with JavaScript.
How is display: table; and all the other related CSS code like tables? And how can it be used?

After days trying to find the answer, I finally found
display: table;
There was surprisingly very little information available online about how to actually getting it to work, even here, so on to the "How":
To use this fantastic piece of code, you need to think back to when tables were the only real way to structure HTML, namely the syntax. To get a table with 2 rows and 3 columns, you'd have to do the following:
<table>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
Similarly to get CSS to do it, you'd use the following:
HTML
<div id="table">
<div class="tr">
<div class="td"></div>
<div class="td"></div>
<div class="td"></div>
</div>
<div class="tr">
<div class="td"></div>
<div class="td"></div>
<div class="td"></div>
</div>
</div>
CSS
#table{
display: table;
}
.tr{
display: table-row;
}
.td{
display: table-cell; }
As you can see in the example below, the divs in the 3rd column have no content, yet are respecting the auto height set by the text in the first 2 columns. WIN!
#table {
display: table;
padding: 5px;
}
.tr {
display: table-row;
padding: 5px;
}
.td {
display: table-cell;
padding: 5px;
width: 150px;
border: #000000 solid 1px;
margin: 5px;
}
<div id="table">
<div class="tr">
<div class="td">Row 1,
<br />Column 1</div>
<div class="td">Row 1, Column 2</div>
<div class="td" style="background:#888888;"></div>
</div>
<div class="tr">
<div class="td">Row 2,
<br />Column 1</div>
<div class="td">Row 2, Column 2</div>
<div class="td" style="background:#888888;"></div>
</div>
</div>
It's worth noting that display: table; does not work in IE6 or 7 (thanks, FelipeAls), so depending on your needs with regards to browser compatibility, this may not be the answer that you are seeking.

It's even easier to use parent > child selector relationship so the inner div do not need to have their css classes to be defined explicitly:
.display-table {
display: table;
}
.display-table > div {
display: table-row;
}
.display-table > div > div {
display: table-cell;
padding: 5px;
}
<div class="display-table">
<div>
<div>0, 0</div>
<div>0, 1</div>
</div>
<div>
<div>1, 0</div>
<div>1, 1</div>
</div>
</div>

How (and why) to use display: table-cell (CSS)
I just wanted to mention, since I don't think any of the other answers did directly, that the answer to "why" is: there is no good reason, and you should probably never do this.
In my over a decade of experience in web development, I can't think of a single time I would have been better served to have a bunch of <div>s with display styles than to just have table elements.
The only hypothetical I could come up with is if you have tabular data stored in some sort of non-HTML-table format (eg. a CSV file). In a very specific version of this case it might be easier to just add <div> tags around everything and then add descendent-based styles, instead of adding actual table tags.
But that's an extremely contrived example, and in all real cases I know of simply using table tags would be better.

The display:table family of CSS properties is mostly there so that HTML tables can be defined in terms of them. Because they're so intimately linked to a specific tag structure, they don't see much use beyond that.
If you were going to use these properties in your page, you would need a tag structure that closely mimicked that of tables, even though you weren't actually using the <table> family of tags. A minimal version would be a single container element (display:table), with direct children that can all be represented as rows (display:table-row), which themselves have direct children that can all be represented as cells (display:table-cell). There are other properties that let you mimic other tags in the table family, but they require analogous structures in the HTML. Without this, it's going to be very hard (if not impossible) to make good use of these properties.

I don't have 10 years of web dev., but only a year or so and I have quickly came around a use case that does not work with table elements and work with and CSS table : forms.
Forms and tables do not go well together. A form is not allowed to be a child of a table element. So, to comment previous comment : divs and CSS table are useful at least when you want forms into table.
Jean-yves

Related

Making HTML <div> tag not take the entire length of the page

I am in the process of making my own website, and I am making it out of pure HTML. I encountered in the making of the page, as I will describe below.
Here's my code for reference :-
<head>
<style>
img {
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
<style>
.sideDiv {
border: 1px outset black;
background-color: white;
text-align: center;
width: 120;
height: 400;
}
</style>
<style>
.mainDiv {
border: 1px outset black;
background-color: white;
text-align: left;
width: 400;
height: 300;
}
</style>
<img src="AyushLogo.png" alt="logo" height="9.2%" width="9.2%" style="float:left">
<br>
<a><button>About Me</button></a>
<a><button>Games</button></a>
<a><button>My Blog</button></a> <br><br>
<hr>
</head>
<body>
<div class="sideDiv">
</div>
<div class="mainDiv">
<p>Hi,<br>My name is Ayush Bhatt.<br><br>I love to code and remake old games. You can view some of my games by clicking on the 'Games' button on the top bar.</p>
</div>
</body>
</html>
The output looks like this :-
I wanted the tag with the "mainDiv" properties to appear at the side of the one with the "sideDiv" properties, but it just doesn't want to.
PS : I want to use only HTML as long as possible
An important thing about <div> tags is that they are known as "block-level" elements, which in particular means that they always start on a new line and take up the full width available, regardless. With this in mind,
writing
<div class="sideDiv"></div>
<div class="mainDiv">
...
</div>
should result in a div with class sideDiv and width as defined in the class, and then a new div with class mainDiv started on a new line, as block-level elements do by default, though note that this is simultaneously also because the div with class sideDiv takes up the remaining width on the page as a block-level element (though its content width is as described in the class, it being a block-level element is a bit like it "reserving" the rest of the width even though its content only uses the amount defined), so the next element (block level or inline) can only start on at least the next line.
If you want to circumvent this behavior, there are many ways to do it. One is by using an external tool like bootstrap, as pointed out by another answer, but my favorite is to simply use flex box. This can be done for your code in this way
<div style="display: flex; flex-direction: row;">
<div class="sideDiv"></div>
<div class="mainDiv">
...
</div>
</div>
A method that directly overwrites the block-level property would be to set the style display: inline-block; for both divs, to prevent either from starting on a new line or taking up the whole available width by default. (Just one isn't enough, if you only set it on the first one, the second still starts on a new line by default, and if you only set it for the second one, the first still takes up all available width by default). However, this causes the element to be treated completely as an inline element besides the fact that block-level height and width can be applied, and can be strange/difficult to maneuver as a result. It is often easier to just use a flex box. Code for this would be
<div class="sideDiv" style="display: inline-block;"></div>
<div class="mainDiv" style="display: inline-block;">
...
</div>
However, note that <p> is also a block-level element, so directly substituting in your original code in the mainDiv div would still cause it to skip a line before displaying. Again, it is usually easier, more modern, and better looking to just use a flex box.
Edit: Added the detail about block-level elements taking up all available width, and fixed the incorrect initial method that changed the display property to overwrite the block-level property by setting display: inline;. This can work, but it will ignore the heights and widths of the <div>s.
try using bootstrap , it deals with layout perfectly , here is an example :
<div class="container">
<div class="row">
<div class="col-md-6">
this is the left section
</div>
<div class="col-md-6">
this is the right section
</div>
</div>
</div>
for more details check :
https://getbootstrap.com/docs/5.0/layout/grid/
NOTE : you will need to include bootstrap and jQuery libs , check for online tutorial to start using bootstrap

how to set a element's width to be from somewhere specific to the end of the page(horizontally)

Here's the problem. I am trying to place some <div> elements beside each other. The width of the divs are not specified and are dependent on their content. I am using the CSS code below to position the <div>s beside each other:
#div{
height: 50px;
float:left;
margin-left:0;
}
I want the last <div>s width to cover the rest of the page (horizontally). With absolute positioning it is possible to set a left position for the last <div> and then use width:100% for the CSS style. But since I don't know the size of the other <div>s, I can not use this approach.
Can anyone help me with my case?
Depending on your browser support needs, you can either use a table-based layout (either with tables or via css) as #user2519211 has shown, or you can use flexbox, which will be much quicker and flexible (ha) in the long run.
You only need to set the container of the elements that you want to cover the page to have display: flex (with browser prefixes included)
Here's a JS Bin showing this: http://jsbin.com/uqepit/2/edit
From there you can do any number of things, including reordering, baseline shifting, etc. If flexbox is an option, Chris Coyer has done some great research on what's currently supported (and behind what syntax). You can see that here:
http://css-tricks.com/snippets/css/a-guide-to-flexbox/
http://css-tricks.com/using-flexbox/
You can either use a table to do this:
<table>
<tr>
<td>asdf</td>
<td>asdf</td>
<td>asdf</td>
<td style="width: 100%;">asdf</td>
</tr>
</table>
Or the display: table css declaration if you must use divs:
<div style="display: table; width: 100%;">
<div style="display: table-cell;">asdf</div>
<div style="display: table-cell;">asdf</div>
<div style="display: table-cell;">asdf</div>
<div style="display: table-cell; width: 100%;">asdf</div>
</div>

table structure to css divs

I really need help converting this simple table structure to css div's. Is there a simple application or something. CSS divs are driving me insane.
<table width="100%" border="0">
<tr>
<td colspan="3" id="Header"></td>
</tr>
<tr>
<td width="20%" id="Nav2"></td>
<td width="40%" id="ContentMiddleLeft"></td>
<td width="40%" id="ContentMiddleRight"></td>
</tr>
<tr>
<td colspan="3" id="BottomContent"></td>
</tr>
</table>
Test this:
EDIT: http://jsfiddle.net/DCbgg/
<style type="text/css" media="screen">
.container {
width: 100%;
}
.left20 {
width: 20%;
float: left;
background: red;
}
.left40 {
width: 40%;
float: left;
background: green;
}
.clear {
clear: both;
}
</style>
<div class="container">
<div class="left20">
Left
</div>
<div class="left20">
Left
</div>
<div class="left40">
Left
</div>
<div class="clear"></div>
<div class="left20">
Left
</div>
<div class="left20">
Left
</div>
<div class="left40">
Left
</div>
</div>
<div class="clear"></div>
First Things First
There are some very important things to remember when changing from table to div layouts that generally apply to all new learning experiences.
Don't get frustrated just because something's not working. Just take a break, look at something else, remember that it's something new and it won't always work the first time. It may take a number of different approaches and attempts before it finally works. You'll get the hang of it eventually.
Especially in this case, remember that divs are vastly different from tables, especially when using them as a major structural part of a site. The thought process behind each is completely different and can take a lot of getting used to for it to click. Because of this:
Not all designs transfer from table to div. Some things are only really easily and properly accomplished with tables, and others with divs. While this is not one of those cases in particular, be open to having to make some design changes when changing your site structure.
That being said, we can now answer the question properly.
An Answer
This is how I would set up the structure using divs:
<div id="wrap">
<div id="header"></div>
<div id="content">
<div id="nav2"></div>
<div id="content_right"></div>
<div style="clear: both"></div>
</div>
<div id="footer"></div>
</div>
And this is what the css would be:
#wrap {
width: 100%;
}
#header {
width: 100%;
height: /* some height value */;
}
#content {
width: 100%;
height: /* some height value */;
}
#nav2 {
width: 20%;
float: left;
}
#content_right {
width: 40%;
float: right;
}
#footer {
width: 100%;
height: /* some height value */;
}
Notes
As I was saying above, the thought process behind tables and divs are quite a bit different. With tables, you're used to using percentages (%) to define widths. This works and is not necessarily a bad thing. It gets the job done and is easy to do.
But when you're using divs, a more common approach is to have fixed widths defined by pixels (px). This allows for a more constant design that won't stretch across the page, and gives you more design freedom, knowing that the page will always be the same width.
For more information on fixed-width design, I would recommend looking at the 960 grid system. It is extremely easy to follow and leads to clean, good-looking designs that are easy to structure and style.
Most importantly, enjoy the new-found freedom that divs bring. They aren't locked in to anything and can literal do anything, be anywhere, and look like anything on a page. There isn't really a limit to what they can do. I've heard them called the only required part of a webpage (You really can design and create an enter page with just divs, text included).
Have fun on your journey!
CSS3 Style (using "display:table;"):
Check http://jsfiddle.net/reKfe/ (jsFiddle made from http://query7.com/exploring-the-power-of-css3)

Is such alignment achievable without <table>?

My goal is an alignment as shown in the attached image (the fields on the left may have any width, but the ones on the right should begin at the same X coordinate).
Right now I am using a simple table code to achieve this:
<table><tr>
<td>Left1</td><td>Right 1</td></tr>
<tr><td>Left 2</td><td>Right 2</td></tr></table>
However, I've heard that using tables is generally bad. Is there a way I could achieve the same design using CSS? The website is being designed for mobile devices which might not support fancy CSS, so the code must be as simple as possible.
EDIT: since I still occasionally get a notification on this question from people who (presumably) are just starting out with HTML like I was when I made it, please refer to the accepted answer by B T as this is by far the best way to achieve this functionality. The question suggested as a "possible duplicate" (31 May 2016) does not currently offer the table-row/table-column CSS-based approach and requires you to do guess work.
I found a much easier way to do this by accident. Say you have the following:
<div class='top'>
<div>Something else</div>
<div class='a'>
<div>Some text 1</div>
<div>Some text 2</div>
</div>
<div class='a'>
<div>Some text 3</div>
<div>Some text 4</div>
</div>
</div>
You can align Some text 1 and Some text 2 using css table display styling like this:
.a {
display: table-row;
}
.a div {
display: table-cell;
}
The coolest thing is that as long as the 'top' div is NOT styled display: table, then other things like "Something else" can be ignored in terms of alignment. If the 'top' div IS styled display: table, then "Some text 1" will be aligned with "Something else" (ie it treats all its children like table rows, even if they have a different display style).
This works in Chrome, not sure if its supposed to behave this way, but I'm glad it works.
.a {
display: table-row;
}
.a div {
display: table-cell;
}
<div class='top'>
<div>Something else</div>
<div class='a'>
<div>Some text 1</div>
<div>Some text 2</div>
</div>
<div class='a'>
<div>Some text 3</div>
<div>Some text 4</div>
</div>
</div>
While it is possible to achieve the same with tables, it would be considered semantically incorrect to use a table for the purpose of layout. Especially since you can achieve the same using just a line or two of CSS.
Give your labels a fixed width (something larger than your longest label text).
<style>
label {
width: 100px;
display: inline-block;
}​
</style>
<label>Name</label>
<input type="text" />
<br/>
<label>Email Address</label>
<input type="text" />​
Example
Here, you could use this for getting the output required.
Using tables IMO is not bad practice, in fact they should be used where tabular data is required, or the format of data resembles a table.
However, designing a full page, or anything not to be displayed in a tabular format, using a table is discouraged, and is in fact very very wrong.
Here goes a sample using a non-table structure:
HTML :
<form>
<label for="name">Email: </label><input id="name" type="email" placeholder="#" />
<br/><br />
<label>Password: </label><input type="password" id="password" placeholder="*"/>
</form>
CSS:
label {
width: 80px;
display: block;
vertical-align: middle;
float:left;
clear:left;
}
input {
border-top-left-radius:5px;
border-bottom-right-radius: 10px;
background: #141414;
color: #fdd56c;
outline: none;
}
Here is an example
Yes, such alignment is possible. Using CSS classes, you can markup your HTML in such a way to achieve the same look of a table without the headache of using a table (or making the markup look ugly).
Using this CSS:
.label {
display: inline-block;
width: 100px;
}
.inputBox {
width: 200px;
}
and this HTML:
<span class="label">E-mail:</span><input type="email"></input><br>
<span class="label">Password:</span><input type="text"></input>
you'll get the layout you want.
To do this with IE7 support, change the CSS above to this:
.label {
display: block;
width: 100px;
float: left;
clear: left;
}
Then, add this line below the lines already shown:
<div style="clear: left"></div>
Example using IE7-compatible settings: http://jsfiddle.net/bbXXp/
True. I am learning it the hard way. I used table for alignment, and now, certain alignments are becoming bizzare in smaller screens (e.g. mobile phone, tablets etc). Hence, am switching over to div. Preferable use <div style="display:inline-block">...</div>, which will align automatically if the screen is smaller.
Hence, my advice is that Table should be used only for genuine tables, and not for aligning controls in a body.

How to style divs like a table (example as attached per SharePoint)?

How can I style a group of related divs to look like a table per the attached image? Thx!
<div class="collection"
<div class="group">
<div class="label">Label1</div>
<div class="value">Value1</div>
</div>
... repeats n times
</div>
Disclaimer: This particular html output is auto-generated and I don't have control over what is generated. I just have divs to work with and I want to style accordingly.
Sorry guys, but, what the float?
while you all tried to proscribe what you think the OP needs, the answer to the question actually is
.collection {display:table}
.group {display:table-row}
.label, .value {display:table-cell}
I believe
.label {
width: 200px;
float: left;
}
(apart from the other styling) will do the thing for you.
html
<div class="collection">
<div>
<div class="label">Label1</div>
<div class="value">Value1</div>
</div>
<div>
<div class="label">Label1</div>
<div class="value">Value1</div>
</div>
</div>
css
.label { float:left; width:200px; border-top:1px solid #ccc; }
.value { margin-left:200px; background:#fffced; border-top:1px solid #ccc; }
Code: http://jsfiddle.net/wWGG8/1/
I would just use a table. You can read about tables in HTML here The <tr> tag defines a table row. The <td> tag defines the table data. Each <td> tag is a new column.
<table>
<tr><td>This is the table data</td><td>This is more table data in the same row</td></tr>
<tr><td>Here is another row</td><td>This is more table data in the second row</td></tr>
</table>
True, you can just use a table. That would be semantically convenient.
Nonetheless, you can stick to your current HTML structure.
Just assign the divs with classes of label and value with a width and then float them to the left.
You might also need to specify a height for the div with class group.