For all my websites so far I have used table layouts but now I wish to try and use a pure CSS layout. But I am really struggling!
How can I emulate the following in CSS:
<table>
<tr>
<td>Some Content 1</td>
<td>Some Content 2</td>
</tr>
</table>
Now lets assume that "Some Content 1" and "Some Content 2" are instead <img> tags. Then the resulting output is two images side by side with centred vertical justification. The size of the two cells in the table are the size of the images plus some padding.
So the table is automatically sized to fit the images or whatever content is inside the cells.
But how do I do this in CSS, it is driving me mad! I am nearly at the point of giving up and just using a table layout, and why not, it is so simple.
Any suggestions most gratefully received.
Thanks,
AJ
Honestly, just stick to tables. Switch to table-less when CSS will offer all the tools needed for grid-like layouts AND all browser will reliably support them.
Your other choice is juggle a lot of hacks and get a spare F5 key for testing.
Then the resulting output is two images side by side with centred vertical justification. The size of the two cells in the table are the size of the images plus some padding.
Do you mean something like this?
<!doctype html>
<html lang="en">
<head>
<title>SO question 2005928</title>
<style>
#images img {
padding: 10px;
vertical-align: middle;
}
</style>
</head>
<body>
<div id="images">
<img src="http://sstatic.net/so/img/logo.png" width="100" height="50">
<img src="http://sstatic.net/so/img/logo.png" width="50" height="100">
</div>
</body>
</html>
Similar layout can be generated using CSS and div tags.
Now a days there many tools available to build such layout using CSS. All modern web page designing tools have these features.
Apart from this tools like Yahoo Grid Builder (link to Yahoo Grid builder) can also be handy for the same.
Change your table, tr, and td tags to div's and make the 'td-divs' float:left. Or, use display:inline-block (with all associated problems), or, use display:table-cell (with all associated problems).
This works in Firefox(haven't tested in other browsers). The borders are just for illustration.
<div>
<div style="float:left; width:49%;border:1px solid black;">
<img style="float:right; width:343px" src="http://www.virginia.edu/german/images/Berlin-City2.jpg"/>
</div>
<div style="float:right; width:49%;border:1px solid black;">
<img src="http://www.virginia.edu/german/images/Berlin-City2.jpg"/>
</div>
</div>
Your question is slightly ambiguous (maybe it's me) but you could also mean this:
<div>
<div style="float:left; width:49%; border:1px solid black;">
<div style="margin:auto; width:343px; border:2px solid red;" >
<img src="http://www.virginia.edu/german/images/Berlin-City2.jpg"/>
</div>
</div>
<div style="float:left; width:49%; border:1px solid black;">
<div style="margin:auto; width:343px; border:2px solid red;" >
<img src="http://www.virginia.edu/german/images/Berlin-City2.jpg"/>
</div>
</div>
</div>
This doesn't satisfy all your requirements but is close.
Forget about the "either or" concept with CSS vs. tables. Both have pros and cons that will drive you up the wall.
I say create as much as you can with CSS, the other layout issues you have, use a table.
Besides, between grid systems and CSS3's TABLE-LAYOUT and template layout module, CSS is really moving towards a "table-based" layout anyway.
The only way I see you can do it otherwise is using <div> tags and setting their properties, such as float in CSS.
I don't think you can actually create a table in CSS, as CSS defines the style of the page and it's elements, not the elements itself.
To make an element behave like a table using pure CSS, use the display property and the values table, table-row, table-cell, inline-table, etc.
This isn't supported by IE, and somewhat defeats the objective of not using tables for columnular layout as the markup is still row based.
Related
I'm getting into Flexbox now, trying to see how I can transition from using the traditional CSS grids.
I have two layouts: One made with a CSS grid. The other one made using Flexbox. The basic layout for both examples is quite basic: A header, a nav, a content section and the footer.
Design-wise they both look the same and behave exactly the same for RWD. However, in order for me to accomplish the same behavior using Flexbox I had to create a wrapper div around the Nav and the Content sections.
This is the HTML used with the CSS grid layout:
<div class="container-12 clear">
<header class="grid-12">Header</header>
<nav class="grid-4">Nav</nav>
<section class="grid-8">Content</section>
<footer class="grid-12">Footer</footer>
</div>
This is the HTML used with the Flexbox layout:
<div class="main-container">
<header>Header</header>
<div class="site-content">
<nav>Nav</nav>
<section>Content</section>
</div>
<footer>Footer</footer>
</div>
Notice the <div class="site-content"> around the nav and section elements.
So my question is: Is the <div class="site-content"> around the nav and section elements necessary in order to accomplish that layout using Flexbox?
I'm trying to achieve the same layout with the same HTML but different CSS techniques.
Here are the demos:
Basic Layout Using a CSS Grid
Basic Layout Using Flexbox
Thanks for any guidance on this.
The answer is simple: Yes, that extra wrapper is required.
I was able to find this article in Smashing Magazine from 2011 By Richard Shepherd where confirms that sometimes an extra wrapping container is needed in order to treat the child elements with Flexbox. Granted, his article uses the old 2009 syntax, but still, the case applies:
Using flexbox often requires an extra div or two, because the parent of any flexbox element needs to have display set to box. Before, you could get away with the following:
<div style="float: left; width: 250px;"> Content here </div>
<div style="float: right; width: 250px;"> Content here </div>
Now with flexbox, you’ll need:
<div style="display: box">
<div style="width: 250px"> Content here </div>
<div style="width: 250px"> Content here </div>
</div>
Many of you have already turned away, insulted by this extra mark-up that is purely for presentation. That’s understandable. But here’s the thing: once you master the CSS, this extra containing div becomes a small price to pay. Indeed, you’ll often already have a containing element (not necessarily a div) to add display: box to, so there won’t be a trade-off at all.
Extract taken from CSS3 Flexible Box Layout Explained
Thanks.
I was trying to vertically align some text inside a div using a CSS table, but it doesn't work for some reason:
<div class="navlink" style="width:150px; display:table;">
<div style="text-align:center; display:table-cell; vertical-align:middle;">Some Text</div>
</div>
Any suggestions on how I can get this code to work?
Works for me, you just put table width instead of height.
<div class="navlink" style="width:150px; display:table;">
---> <div class="navlink" style="height:150px; display:table;">
It works, it's simply that you are not using any height for your cell div, so do it like this
Demo
<div class="navlink" style="width:150px; display:table;">
<div style="text-align:center; display:table-cell; height: 200px; vertical-align:middle;">Some Text</div>
</div>
This is the best answer I've found: http://phrogz.net/css/vertical-align/index.html
This comes up a lot. There's no easy answer.
A quote from the page:
A FAQ on various IRC channels I help out on is "How do I vertically
center my stuff inside this area?" This question is often followed by
"I'm using vertical-align:middle but it's not working!"
The problem here is three-fold:
A HTML layout traditionally was not designed to specify vertical
behavior. By its very nature, it scales width-wise, and the content
flows to an appropriate height based on the available width.
Traditionally, horizontal sizing and layout is easy; vertical sizing
and layout was derived from that.
B The reason vertical-align:middle isn't doing what is desired want
is because the author doesn't understand what it's supposed to do, but
…
C … this is because the CSS specification really screwed this one
up (in my opinion)—vertical-align is used to specify two completely
different behaviors depending on where it is used.
The article goes on to explain that there are two basic methods: absolute positioning, and the line-height method in the other answers.
I cannot figure out this positioning problem in Firefox. It doesn't seem to follow the absolute positioning rule. Is there something I'm doing that shouldn't be done, but some browesers handle it and some don't?
JS Fiddle:
Original - http://jsfiddle.net/g9qzh/
Updated - http://jsfiddle.net/g9qzh/2/
Works in IE, Chrome, Safari, Opera
Here's the actual code. Let me know if I'm not following some kind of standard I don't know about.
HTML:
<table>
<tr>
<td>
<div id="three">Three</div>
<div id="two">Two</div>
</td>
<tr>
<tr>
<td>
<div id="three">Three</div>
<div id="two">Two</div>
</td>
<tr>
</table>
CSS:
#two {
position: absolute;
top: 0;
}
td {
position: relative;
}
My only clue is that there is some other value that I should assign to td that would cause it to work. Some other stackoverflow questions have mentioned Firefox misbehaving with this, but I haven't been able to find an answer. I tried assigning both top and left values of zero, but FF won't budge.
Change ID's to classes and also displaying it as blocks fixes it:
http://jsfiddle.net/GchWZ/
It is better and more "proper" to user an inner div though as quoted from this stack overflow post: Does Firefox support position: relative on table elements?
<td>
<div style="position:relative">
This will be positioned normally
<div style="position:absolute; top:5px; left:5px;">
This will be positioned at 5,5 relative to the cell
</div>
</div>
</td>
You are using IDs
IDs are unique. Use Classes if you want to reuse a style assignment.
The problem comes from how FF renders tables. If you set your TDs to display:inline-block; it should display correctly.
Try this:
<tr>
<td>
<div id="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
</tr>
<tr>
<td>
<div id="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
</tr>
and for css:
#two {
position: absolute;
top: 0px;
}
#wrapper {
position: relative;
}
Aside from the duplicate ID issue noted by Brandt, assigning positioning to table cells is dodgy at best - I'm surprised it works in any browsers. If you must use a table, wrap the elements you want to position in a div and assign the wrapper div position: relative:
<table>
<tr>
<td>
<div class="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
<tr>
</table>
CSS
#two {
position: absolute;
top: 0;
}
.wrapper {
position: relative;
}
In case you want to position stuff at the top and bottom of a cell, also in Firefox, I made it work doing the following mix of CSS and (unfortunately) jQuery.
Use a wrapper div (div.inner) inside your td which has position=relative style in the td. Inside the wrapper I added 2 divs which are to be positioned at the top and bottom of the cell.
Positioning at the top (class=interval-start) is for free, via CSS positioning.
Positioning the div.interval-end at the bottom is done via script, which adds the styling shown in the picture. With variable td-heights and the wrapper div being 0-height by default, you need a way to tell the element how far it should go to the bottom. The script is as follows:
$("table .inner .interval-end").each(function () {
$(this).css({top: ($(this).parent().parent().height() - 10) + "px"})
}).show()
I initially made the div.interval-end invisible, set the 'top' style, and then made it visible via jQuery show().
Hope this helps anybody trying to achieve the same. Let me know if there are better methods out there, specially if these methods do not require scripting. BTW: I tried setting the height style of the wrapper div.inner, but it messes with the table layout in Firefox.
There are legitimate reasons to use CSS display: table styling. It eliminates issues that display: block and display: inline-block do not address. These reasons occupy an entire chapter of a book on CSS styling so I won't go into them here. That same book also describes the problem of positioning within items with that display type. CSS 2.1 specs simply don't address the issue and Mozilla has chosen a course that ignores attempts to create a positioning context with those elements. CSS-table positioning is well established, mature methodology, and not "dodgy" - it just takes understanding of its limits - just like any other CSS element. For liquid layouts and other layouts where element size is variable or unknown it's indispensable for vertical spacing and positioning.
One suggestion in this thread has been presented - create a div within the "table-cell" element set to position: relative and use that for the positioning context. The other method is to embed another CSS table within that cell and use it to position elements within a grid. The third method is to wrap your CSS table within another item that creates a positioning context.
I'm trying to code a layout somewhat similar to SO.
It has a centered container with typical blocks: header, navigation, content area and footer. This blocks have different background-color. The problem is, I want the background to be 100% of the screen width.
You can see this in SO's userbar at the top of the screen.
Also I made an example picture. Note, that there shouldn't be any vertical borders, they're just to show the content area.
I've checked SO's html source but it didn't tell me anything
So, what are my options?
My first idea was to make a wrapper div for each section which handles the background, and another content div inside of it with width:950px and margin:0 auto
But it seems to me very inefficient.
Is there a nicer way to make it?
I've ended up with this structure:
<body>
<div id="header">
<div id="logo-container" class="wrap">
<div>...</div>
</div>
<div id="navigation" class="wrap">
<div>...</div>
</div>
</div>
...
<body>
and the style looks like
#... {
background:#...
}
.wrap div {
width:950px;
margin:0 auto;
}
Thanks everyone.
What I do in cases like that is style the html or body with the main background color (the one for your content), then keep the header and footer out of the main wrapper and size down their contents as needed, so I'd end up with something like so (which I think is similar to what you're saying you did, but with a couple minor differences):
<body style="background: #000;">
<div id="header" style="width: 100%; background: #666;">
<div id="nav" style="width: 100%; background: #999;">
<ul class="navigation" style="width: 950px; margin: 0 auto;">
</ul>
</div>
</div>
<div id="contentWrap" style="width: 950px; margin: 0 auto;">
Whatever content stuff, other divs, etc.
</div>
<div id="footer" style="width: 100%; background: #999;">
</div>
</body>
You don't really need extra wrappers if you have only a couple block level elements in your header and footer, so you end up with about the same number of divs as if you had them all in one wrapper. You can also keep their sizes in sync if you put them in one CSS call with the size. It might sacrifice a little bit in the way of CSS efficiency, but in my experience, it's a small enough trade off that it's not worth losing sleep over, since either the site is small enough that it doesn't matter, or large enough that there are better efficiency increases in places like the images, javascript, and server-side code.
I prefer working with CSS based design, but as more of a back end coder my CSS skills are a bit weak. When I get involved with layout, I tend to fall back on table based formatting because my mind has been warped by years of table based abuse. There's one particular problem that I always trip over. What is the best CSS alternative to:
<table width="100%">
<tr>
<td align="center">
content goes here
</td>
</tr>
</table>
I sometimes use:
<div style="width:100%; text-align:center">content</div>
But this doesn't seem quite right. I'm not trying to align text, I'm trying to align content. Also, this seems to have an effect on the text alignment of enclosed elements, which requires tweaking to fix. One thing I don't get is: why isn't there a float:center style? It seems like that would be the best solution. Hopefully, I'm missing something and there is a perfect CSS way to do this.
You are right that text-align is intended for aligning text. It's actually only Internet Explorer that lets you center anything other than text with it. Any other browser handles this correctly and doesn't let block elements be affected by text-align.
To center block elements using css you use margin: 0 auto; just as Joe Philllips suggested. Although you don't need to keep the table at all.
The reason that there is no float: center; is that floating is intended to place elements (typically images) either to the left or the right and have text flow around them. Floating something in the center doesn't make sense in this context as that would mean that the text would have to flow on both sides of the element.
I would recommend putting a <div> into your <td> and setting the style attribute to style="width: 200px; margin: 0 auto;"
The catch is that you must set a fixed width.
Edit:
After looking at the question again, I would recommend scrapping the table entirely. Just use a <div style="width: 200px; margin: 0 auto;> as I suggested and no need for a table.
Here is a good resource for centering using CSS.
http://www.w3.org/Style/Examples/007/center
This demonstrates how to center text, blocks, images and how to center them vertically.
Where do you find yourself commonly doing this? For me - I am most often trying to center the entire design of the site, so I usually do this:
<html>
<body>
<div id="wrapper">
<div id="header">
</div>
<div id="content">
</div>
<div id="footer">
</div>
</div>
</body>
</html>
body {text-align:center;}
#wrapper {margin:0 auto; text-align:left; width:980px;}
This will center the entire design on the page at 980px width, while still leaving all of your text left aligned (as long as that text is within the #wrapper element).
Use display:inline-block to enable text-align:center and center content without a fixed width:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Centering</title>
<style type="text/css">
.container { text-align:center; }
/* Percentage width */
.wrapper { width: 99%; }
/* Use inline-block for wrapper */
.wrapper { display: inline-block; }
/* Use inline for content */
.content { display:inline; }
</style>
</head>
<body>
<div class="container">
<div class="content">
<div class="wrapper">
<div>abc</div>
<div>xyz</div>
</div>
</div>
</div>
</body>
</html>
d03boy's answer is correct for the right way to center things.
To answer your other comment, "Also, this seems to have an effect on the text alignment of enclosed elements, which requires tweaking to fix." That's the nature of how CSS works, setting a property on an element affects all of its children, unless the property is overridden by one of them (assuming the property is one that is inherited, of course).