How to approximate table layout with css when structure is disjointed - html

I have some HTML which I want to use display: table css attributes to control. Unfortunately, I cannot actually change the HTML (or JS either), only the CSS (long story). This is a problem, because the structure of the existing HTML is causing trouble for the table layout. Here is a simplified version of the HTML and CSS:
<style>
.like-table { display: table;}
.like-tr { display: table-row;}
.like-th { display: table-cell; border: 1px solid gray;}
.useless-div-1 { }
.useless-div-2 { }
.like-td { display: table-cell; border: 1px solid gray;}
</style>
<div class="like-table">
<div class="like-tr">
<div class="like-th">1</div>
<div class="like-th">22</div>
<div class="like-th">3</div>
</div>
<div class="useless-div-1"><div class="useless-div-2">
<div class="like-tr">
<div class="like-td">111</div>
<div class="like-td">2</div>
<div class="like-td">3</div>
</div>
<div class="like-tr">
<div class="like-td">11</div>
<div class="like-td">2</div>
<div class="like-td">333</div>
</div>
</div></div>
</div>
Sadly, this renders the header and body columns width different widths:
If I remove the "useless-div-*" open and closing tags:
<div class="like-table">
<div class="like-tr">
<div class="like-th">1</div>
<div class="like-th">22</div>
<div class="like-th">3</div>
</div>
<div class="like-tr">
<div class="like-td">111</div>
<div class="like-td">2</div>
<div class="like-td">3</div>
</div>
<div class="like-tr">
<div class="like-td">11</div>
<div class="like-td">2</div>
<div class="like-td">333</div>
</div>
</div>
Then it renders fine, aligning header and body column widths:
So, is there anything I can do to the CSS that will cause the first set of HTML to behave like the second? Remember I cannot modify the HTML or JavaScript -- only the CSS! Please do not ask why...
Click here to tinker with the code.

Since you're wrapping table-row elements by useless-div, you could simply set display property of useless-div to table-row-group:
.useless-div { display: table-row-group; }
In CSS table layouts, all elements should follow the same structural properties.
Here is the JSBin Demo.
Update
After scratching my head for the past 5 hours over this, I realized that it's impossible to handle this by the current way.
So, I decided to write new styles to create a flexible CSS table. But I should mention a few things at first:
To keep the columns aligned vertically, setting a specific width to cells is required.
In the following example, I set borders to display the table better. because of that, I used box-sizing property to force browser to calculate the width of each cell including its padding and border. If you don't need border, remove it and the border-box property as well.
The Approach
.like-table {
width: 400px; /* You could declare a specific width. Your choice */
margin: 0 auto;
}
.like-th, .like-td {
float: left; /* <-- Float the cells to stick together */
width: 33.33%; /* <-- I applied the same width on each cell. */
/* I've explained how to set specific width for each column in the following */
border: 1px solid gray; /* Add border around each cell */
-webkit-box-sizing: border-box; /* Force browser to calculate width+borders */
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.like-tr:after { /* Clearfix hack */
content: ' ';
font: 0/0 a;
display: block;
clear: both;
}
Note: To apply specific width on each column (left + center + right), First set a width on each cell as I did at above, then use the following selectors to override the applied width for left and right columns:
.like-table .like-td:first-child, /* Selectors for the left column */
.like-table .like-th:first-child {
width: 100px; /* <-- Override the width for the left column */
border-right: 0; /* You might also want to remove right borders */
}
.like-table .like-td:last-child, /* Selectors for the right column */
.like-table .like-th:last-child {
width: 100px; /* <-- Override the width for the right column */
border-left: 0; /* You might also want to remove left borders */
}
JSBin Demo #1. (fluid width)
JSBin Demo #2. (fixed width)

Related

How to set text to be at the right side of the screen

I'm trying to replicate the front page of Fanfiction.Net as a personal assignment for myself but I don't know how to place the text in different places in the screen (Left, Center and Right all on the same line)
body {
background-color: lightyellow
}
<div style="background-color: blue">
<table align="left">
<tr>
<hi style="color: white">Fanfiction.NET| Unleash your Imagination</hi>
</tr>
<tr style=""><input type="text" placeholder="Search.."></tr>
</table>
</div>
I'm trying to make the search bar appear at the right side of the header but don't know how.
Read up on this! Should explain everything you need. (Put it inside style="")
https://www.w3schools.com/cssref/pr_text_text-align.ASP
It's a combination of good HTML structure and styling. Part of the styling is using text-align: left or right but you will also need to structure your code the right way.
Right now you're using a table to structure your page. This is "HTML abuse" from the old days when we where very limited. These days a table is just used for displaying data (like you would expect from a table), not to style your page. For this we use other elements like divs. Of course it's very understandable that you want to order your page in columns. So you can still do that by telling your divs that they need to behave like a grid. And inside that grid you can put other divs that will behave like columns. See the example below.
body {
margin: 0;
}
.blue-bar {
background-color: rgb(51, 51, 153);
padding: 10px 0;
font-family: sans-serif;
color: white;
}
.grid-container {
width: 80%; /* Or 1300px or 780px or ... just not the whole thing */
margin: auto; /* If width is not 100% margin auto will position it in the middle */
display: grid; /* Defines that we'll use a grid-system in this div */
grid-template-columns: 70% 30%; /* inside our grid-container are 2 divs, for 2 columns. these are their sizes */
}
.column-left {
background-color: rgba(0, 0, 0, 0.5); /* Remove this, just visual help */
text-align: left;
}
.column-right {
background-color: rgba(0, 0, 0, 0.3); /* Remove this, just visual help */
text-align: right;
}
<div class="blue-bar">
<div class="grid-container">
<div class="column-left">FanFiction | unleash your imagination</div>
<div class="column-right"> Login | Sign up </div>
</div>
</div>
If you just started to learn HTML don't make the mistake to make your grids to complex. Just focus on a grid with one row and maybe two, three or four columns. (like the example of the topbar). Don't be to hasty to add rows in the beginning, those can get pretty confusing!

Make rounded corners for nested div

I'm trying to make a rounded corners for my responsive table using div but the top part of the div isn't being rounded.
This is how my current preview looks like:
Full code: http://jsfiddle.net/ajt98kqy/
My HTML structure:
<div class="coltable">
<div class="col">
<h4>Name</h4>
<p>John</p>
</div>
<div class="col">
<h4>Title</h4>
<p>Manager</p>
</div>
What I want to achieve is rounded corner (top border isn't rounded yet). How can I fix this?
Your inner content is currently overflowing and is visible. You need to add the CSS property overflow: hidden.
So it will be like:
.coltable {
....
overflow: hidden;
}
In this way no matter how many inner items you add it will always be rounded at the top and bottom.
You need to round the h4 element depending on which column it is in. For example:
.coltable .col h4 {
margin: 0;
padding: .75rem;
border-bottom: 2px solid #dee2e6;
background-color: blue;
padding-left: 40px;
color: #fff;
border-radius: 10px 0 0 0; // add this to your code
}
.coltable .col:last-child h4 {
border-radius: 0 10px 0 0;
}
The values represent each corner, starting from the top left and going around clockwise.
I've targeted the right column by using last-child pseudo; if you add an extra 3rd column, it will still work.
Here is an updated fiddle: http://jsfiddle.net/ajt98kqy/3/
If you are using Bootstrap 4, you can add the class "rounded" to your div.
e.g "<div class="coltable rounded">
Otherwise you can use the style "border-radius" by doing either of the following.
Inline styling:
<div class="coltable" style="border-radius: 5px;">
External Styling:
CSS :
.rounded{
border-radius: 5px; // This will round every side of your border.
}
HTML :
<div class="coltable rounded">
Remember if you are using external CSS, you will have to link to your css file in the
<head> tag of your document.
<link rel="stylesheet" href="path/to/file/nameofcssfile.css">
Add overflow: hidden; into .coltable class.
Your div .col class is overlaping your .coltable div.

Make two parallel `<div>` colums the same height

Suppose I have two columns, both represented by a <div> block. Both columns may grow larger than the other, so I want to force the smaller one to grow as big as the other.
Example of my problem: http://jsfiddle.net/TvnSJ/
As you can see, the second column is smaller.
I managed to solve this using tables, but I was unable to add margin between them. The margin is important, so I would like to know another solution.
You can use display: table and display: table-cell. Here is your fiddle updated: http://jsfiddle.net/TvnSJ/2/
This makes the divs render like tds. Basically you can get the layout of a table without using a table when it is semantically incorrect. I don't think you can float them however.
Edit: I just noticed the bit about margin. You can add padding to these, or you could wrap the content in another element and add margin to that if you need the separation to not include the background colour.
This can be achieved in CSS3 with the new box model:
.box {
width:100px;
display:box;
/* Firefox */
display:-moz-box;
-moz-box-orient:horizontal;
/* Safari, Opera, and Chrome */
display:-webkit-box;
-webkit-box-orient:horizontal;
/* W3C */
display:box;
box-orient:horizontal;
}
.box .column1 {
-moz-box-flex:1.0; /* Firefox */
-webkit-box-flex:1.0; /* Safari and Chrome */
-ms-flex:1.0; /* Internet Explorer 10 */
box-flex:1.0;
background: yellow;
}
.box .column2 {
-moz-box-flex:1.0; /* Firefox */
-webkit-box-flex:1.0; /* Safari and Chrome */
-ms-flex:1.0; /* Internet Explorer 10 */
box-flex:1.0;
background: green;
}
And the HTML
<div class="box">
<div class="column1">
a<br>b
</div>
<div class="column2">
a
</div>
</div>
I made this with the examples from here http://www.w3schools.com
Fiddle http://jsfiddle.net/w5ELr/
Here's another approach using 2 containers that I used recently
<div class="container2">
<div class="container1">
<div class="col1">
a<br />b<br />c
</div>
<div class="col2">
a
</div>
</div>
</div>
CSS:
.container2 {
clear:left;
float:left;
width:100px;
overflow:hidden;
background:blue; /* column 2 background colour */
color: white;
}
.container1 {
float:left;
width:100px;
position:relative;
right:50%;
background:green; /* column 1 background colour */
color: white;
}
.col1 {
float:left;
width:46%;
position:relative;
left:52%;
overflow:hidden;
}
.col2 {
float:left;
width:46%;
position:relative;
left:56%;
overflow:hidden;
}
Fiddle: http://jsfiddle.net/Lunf6/1/
Inspired from: http://matthewjamestaylor.com/blog/equal-height-columns-2-column.htm
if you want the same but using table:
<table style="width: 100%;">
<tbody>
<tr>
<td style="background: #006600;">a<br/>b</td>
<td style="width: 5px;"></td>
<td style="background: #BB0000;">a</td>
</tr>
</tbody>
</table>
you can style your table and its cells as you like with paddings, margins, etc:
.TABLE-DEFAULT{
border : 0px;
border-collapse : separate;
border-spacing : 0px;
width : 100%;
background : transparent;
}
.TABLE-DEFAULT td{
padding: 4px;
}
.TABLE-DEFAULT td:FIRST-CHILD{
padding: 0px;
}
.....etc
Despite question #2 solves the question fully and satisfactorily, it has a big drawback to consider: It doesn't works in IE7 and below.
If you need too support old browsers, there's another approach based on padding, margin and overflow properties. It's a little bit tricky, but it works:
Define a container div, which works as a "colum-row", like this:
<div class="column-row"></div>
.column-row {overflow: hidden}
Then put some columns in it. And style them setting padding and margin to force a fake overflow:
<div class="column-row">
<div class="column">Column 1</div>
<div class="column">Column 2</div>
...
</div>
.column-row {overflow: hidden}
.column {float: left; padding-bottom: 99999; margin-bottom: -99999}
So, you'll get a bunch of columns which they looks equal sized, where their height value corresponds to the largest one.
I have edited the previows jsFiddle (now at http://jsfiddle.net/TvnSJ/16/) if you want to play with a working example.
To get two divs the same height automatically after adding content to one, you'll need to use javascript or jquery. Here is the below jQuery that can do this for you. Just change #column-1 to the ID of your first colum and #column-2 to the ID of your second column.
$(document).ready(function(){
x = $('#column-1').height();
y = $('#column-2').height();
if x > y {
$('#column-2').height(x);
else {
$('#column-1').height(y);
}
});

How to make a vertical line in HTML

How do you make a vertical line using HTML?
Put a <div> around the markup where you want the line to appear to next, and use CSS to style it:
.verticalLine {
border-left: thick solid #ff0000;
}
<div class="verticalLine">
some other content
</div>
You can use the horizontal rule tag to create vertical lines.
<hr width="1" size="500" style="0 auto" />
By using minimal width and large size, horizontal rule becomes a vertical one.
You can use an empty <div> that is styled exactly like you want the line to appear:
HTML:
<div class="vertical-line"></div>
With exact height (overriding style in-line):
div.vertical-line{
width: 1px; /* Line width */
background-color: black; /* Line color */
height: 100%; /* Override in-line if you want specific height. */
float: left; /* Causes the line to float to left of content.
You can instead use position:absolute or display:inline-block
if this fits better with your design */
}
<div class="vertical-line" style="height: 45px;"></div>
Style the border if you want 3D look:
div.vertical-line{
width: 0px; /* Use only border style */
height: 100%;
float: left;
border: 1px inset; /* This is default border style for <hr> tag */
}
<div class="vertical-line" style="height: 45px;"></div>
You can of course also experiment with advanced combinations:
div.vertical-line{
width: 1px;
background-color: silver;
height: 100%;
float: left;
border: 2px ridge silver ;
border-radius: 2px;
}
<div class="vertical-line" style="height: 45px;"></div>
You can also make a vertical line using HTML horizontal line <hr />
html, body{height: 100%;}
hr.vertical {
width: 0px;
height: 100%;
/* or height in PX */
}
<hr class="vertical" />
There is no vertical equivalent to the <hr> element. However, one approach you may want to try is to use a simple border to the left or right of whatever you are separating:
#your_col {
border-left: 1px solid black;
}
<div id="your_col">
Your content here
</div>
HTML5 custom elements (or pure CSS)
1. javascript
Register your element.
var vr = document.registerElement('v-r'); // vertical rule please, yes!
*The - is mandatory in all custom elements.
2. css
v-r {
height: 100%;
width: 1px;
border-left: 1px solid gray;
/*display: inline-block;*/
/*margin: 0 auto;*/
}
*You might need to fiddle a bit with display:inline-block|inline because inline won't expand to containing element's height. Use the margin to center the line within a container.
3. instantiate
js: document.body.appendChild(new vr());
or
HTML: <v-r></v-r>
*Unfortunately you can't create custom self-closing tags.
usage
<h1>THIS<v-r></v-r>WORKS</h1>
example: http://html5.qry.me/vertical-rule
Don't want to mess with javascript?
Simply apply this CSS class to your designated element.
css
.vr {
height: 100%;
width: 1px;
border-left: 1px solid gray;
/*display: inline-block;*/
/*margin: 0 auto;*/
}
*See notes above.
One other option is to use a 1-pixel image, and set the height - this option would allow you to float it to where you need to be.
Not the most elegant solution though.
You can draw a vertical line by simply using height / width with any html element.
#verticle-line {
width: 1px;
min-height: 400px;
background: red;
}
<div id="verticle-line"></div>
There is a <hr> tag for horizontal line. It can be used with CSS to make horizontal line also:
.divider{
margin-left: 5px;
margin-right: 5px;
height: 100px;
width: 1px;
background-color: red;
}
<hr class="divider">
The width property determines the thickness of the line. The height property determines the length of the line. The background-color property determines the color of the line.
There isn't any tag to create a vertical line in HTML.
Method: You load a line image. Then you set its style like "height: 100px ; width: 2px"
Method: You can use <td> tags <td style="border-left: 1px solid red; padding: 5px;"> X </td>
To create a vertical line centered inside a div I think you can use this code.
The 'container' may well be 100% width, I guess.
div.container {
width: 400px;
}
div.vertical-line {
border-left: 1px solid #808080;
height: 350px;
margin-left: auto;
margin-right: auto;
width: 1px;
}
<div class="container">
<div class="vertical-line"> </div>
</div>
Rotate a <hr> 90 degrees:
<hr style="width:100px; transform:rotate(90deg);">
You can use hr (horizontal line) tag and than rotate it 90 degree with css below
hr {
transform:rotate(90deg);
-o-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
}
http://jsfiddle.net/haykaghabekyan/0c969bm6/1/
One more approach is possible : Using SVG.
eg :
<svg height="210" width="500">
<line x1="0" y1="0" x2="0" y2="100" style="stroke:rgb(255,0,0);stroke-width:2" />
Sorry, your browser does not support inline SVG.
</svg>
Pros :
You can have line of any length and orientation.
You can specify the width, color easily
Cons :
SVG are now supported on most modern browsers. But some old browsers (like IE 8 and older) don't support it.
I used a combination of the "hr" code suggested, and here's what my code looks like:
<hr style="width:0.5px; height:500px; position: absolute; left: 315px;"/>
I simply changed the value of the "left" pixel value to position it. (I used the vertical line to line-up content on my webpage, and then I removed it.)
Vertical line right to the div
<div style="width:50%">
<div style="border-right:1px solid;">
<ul>
<li>
Empty div didn't shows line
</li>
<li>
Vertical line length depends on the content in the div
</li>
<li>
Here I am using inline style. You can replace it by external style or internal style.
</li>
</ul>
</div>
</div>
Vertical line left to the div
<div style="width:50%">
<div style="border-left:1px solid;">
<ul>
<li>
Empty div didn't shows line
</li>
<li>
Vertical line length depends on the content in the div
</li>
<li>
Here I am using inline style. You can replace it by external style or internal style.
</li>
</ul>
</div>
</div>
Why not use &#124, which is the html special character for |
If your goal is to put vertical lines in a container to separate side-by-side child elements (column elements), you could consider styling the container like this:
.container > *:not(:first-child) {
border-left: solid gray 2px;
}
This adds a left border to all child elements starting from the 2nd child. In other words, you get vertical borders between adjacent children.
> is a child selector. It matches any child of the element(s) specified on the left.
* is a universal selector. It matches an element of any type.
:not(:first-child) means it's not the first child of its parent.
Browser support: > * :first-child and :not()
I think this is better than a simple .child-except-first {border-left: ...} rule, because it makes more sense to have the vertical lines come from the container's rules, not the different child elements' rules.
Whether this is better than using a makeshift vertical rule element (by styling a horizontal rule, etc.) will depend on your use case, but this is an alternative at least.
To add a vertical line you need to style an hr.
Now when you make a vertical line it will appear in the middle of the page:
<hr style="width:0.5px;height:500px;"/>
Now to put it where you want you can use this code:
<hr style="width:0.5px;height:500px;margin-left:-500px;margin-right:500px;"/>
This will position it to the left, you can inverse it to position it to the right.
In the Previous element after which you want to apply the vertical row , You can set CSS ...
border-right-width: thin;
border-right-color: black;
border-right-style: solid;
Simply use either of the UTF-8 Miscellaneous Symbols
|
|
That's all you need and its compatible with all browsers.
Thanks me later.
For an inline style I used this code:
<div style="border-left:1px black solid; position:absolute; left:50%; height:300px;" />
and that positioned it directly in the center.
I needed an inline vertical line, so I tricked a button into becoming a line.
<button type="button" class="v_line">l</button>
.v_line {
width: 0px;
padding: .5em .5px;
background-color: black;
margin: 0px; 4px;
}
I think it is a simple way not do to anything more You can change border left or right according to your need
.vertical-line{
border-left:1px solid #000
}
<span class="vertical-line"></span
You can also use the HTML symbol | which renders as '|'
To make the vertical line to center in the middle use:
position: absolute;
left: 50%;

Can you do this HTML layout without using tables?

Ok, I had a simple layout problem a week or two ago. Namely sections of a page needed a header:
+---------------------------------------------------------+
| Title Button |
+---------------------------------------------------------+
Pretty simple stuff. Thing is table hatred seems to have taken over in the Web world, which I was reminded of when I asked Why use definition lists (DL,DD,DT) tags for HTML forms instead of tables? Now the general topic of tables vs divs/CSS has previously been discussed, for example:
DIV vs Table; and
Tables instead of DIVs.
So this isn't intended to be a general discussion about CSS vs tables for layout. This is simply the solution to one problem. I tried various solutions to the above using CSS including:
Float right for the button or a div containing the button;
Position relative for the button; and
Position relative+absolute.
None of these solutions were satisfactory for different reasons. For example the relative positioning resulted in a z-index issue where my dropdown menu appeared under the content.
So I ended up going back to:
<style type="text/css">
.group-header { background-color: yellow; width: 100%; }
.group-header td { padding: 8px; }
.group-title { text-align: left; font-weight: bold; }
.group-buttons { text-align: right; }
</style>
<table class="group-header">
<tr>
<td class="group-title">Title</td>
<td class="group-buttons"><input type="button" name="Button"></td>
</tr>
</table>
And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.
So can anyone do the equivalent without tables?
The requirements are:
Backwards compatible: to FF2 and IE6;
Reasonably consistent: across different browsers;
Vertically centered: the button and title are of different heights; and
Flexible: allow reasonably precise control over positioning (padding and/or margin) and styling.
On a side note, I came across a couple of interesting articles today:
Why CSS should not be used for layout; and
Tables vs CSS: CSS Trolls begone
EDIT: Let me elaborate on the float issue. This sort of works:
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; overflow: hidden; }
.group-content { border: 1px solid black; background: #DDD; }
.group-title { float: left; padding: 8px; }
.group-buttons { float: right; padding: 8px; }
</style>
</head>
<body>
<div class="group-header">
<div class="group-title">This is my title</div>
<div class="group-buttons"><input type="button" value="Collapse"></div>
</div>
<div class="group-content">
<p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
<p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
<p>On a side note, I came across a couple of interesting articles today:</p>
</div>
</body>
</html>
Thanks to Ant P for the overflow: hidden part (still don't get why though). Here's where the problem comes in. Say I want the title and button to be vertically centered. This is problematic because the elements are of different height. Compare this to:
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; overflow: hidden; }
.group-content { border: 1px solid black; background: #DDD; }
.group-header td { vertical-align: middle; }
.group-title { padding: 8px; }
.group-buttons { text-align: right; }
</style>
</head>
<body>
<table class="group-header">
<tr>
<td class="group-title">This is my title</td>
<td class="group-buttons"><input type="button" value="Collapse"></td>
</tr>
</table>
<div class="group-content">
<p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
<p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
<p>On a side note, I came across a couple of interesting articles today:</p>
</div>
</body>
</html>
which works perfectly.
There is nothing wrong with using the tools that are available to you to do the job quickly and correctly.
In this case a table worked perfectly.
I personally would have used a table for this.
I think nested tables should be avoided, things can get messy.
Just float left and right and set to clear both and you're done. No need for tables.
Edit: I know that I got a lot of upvotes for this, and I believed I was right. But there are cases where you simply need to have tables. You can try doing everything with CSS and it will work in modern browsers, but if you wish to support older ones... Not to repeat myself, here the related stack overflow thread and rant on my blog.
Edit2: Since older browsers are not that interesting anymore, I'm using Twitter bootstrap for new projects. It's great for most layout needs and does using CSS.
Float title left, float button right, and (here's the part I never knew until recently) - make the container of them both {overflow:hidden}.
That should avoid the z-index problem, anyway. If it doesn't work, and you really need the IE5 support, go ahead and use the table.
This is kind of a trick question: it looks terribly simple until you get to
Say I want the title and button to be vertically centered.
I want to state for the record that yes, vertical centring is difficult in CSS. When people post, and it seems endless on SO, "can you do X in CSS" the answer is almost always "yes" and their whinging seems unjustified. In this case, yes, that one particular thing is hard.
Someone should just edit the entire question down to "is vertical centring problematic in CSS?".
In pure CSS, a working answer will one day be to just use "display:table-cell". Unfortunately that doesn't work across current A-grade browsers, so for all that you might as well use a table if you just want to achieve the same result anyway. At least you'll be sure it works far enough into the past.
Honestly, just use a table if it's easier. It won't hurt.
If the semantics and accessibility of the table element really matter to you, there is a working draft for making your table non-semantic:
http://www.w3.org/TR/wai-aria/#presentation
I think this requires a special DTD beyond XHTML 1.1, which would just stir up the whole text/html vs application/xml debate, so let's not go there.
So, on to your unresolved CSS problem...
To vertically align two elements on their center: it can be done a few different ways, with some obtuse CSS hackery.
If you can fit within the following constraints, then there is a relatively simple way:
The height of the two elements is fixed.
The height of the container is fixed.
The elements will be narrow enough not to overlap (or can be set to a fixed width).
Then you can use absolute positioning with negative margins:
.group-header { height: 50px; position: relative; }
.group-title, .group-buttons { position: absolute; top: 50%; }
# Assuming the height of .group-title is a known 34px
.group-title { left: 0; margin-top: -17px; }
# Assuming the height of .group-buttons is a known 38px
.group-buttons { right: 0; margin-top: -19px; }
But this is pointless in most situations... If you already know the height of the elements, then you can just use floats and add enough margin to position them as needed.
Here is another method which uses the text baseline to vertically align the two columns as inline blocks. The drawback here is that you need to set fixed widths for the columns to fill out the width from the left edge. Because we need to keep the elements locked to a text baseline, we can't just use float:right for the second column. (Instead, we have to make the first column wide enough to push it over.)
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; }
.valign { display: inline-block; vertical-align: middle; }
.group-content { border: 1px solid black; background: #DDD; }
.group-title { padding: 8px; width: 384px; }
.group-buttons { padding: 8px; width: 84px; text-align: right; }
</style>
<!--[if lt IE 8]>
<style type="text/css">
.valign { display: inline; margin-top: -2px; padding-top: 1px; }
</style>
<![endif]-->
</head>
<body>
<div class="group-header">
<div class="valign">
<div class="group-title">This is my title.</div>
</div><!-- avoid whitespace between these! --><div class="valign">
<div class="group-buttons"><input type="button" value="Collapse"></div>
</div>
</div>
<div class="group-content">
<p>And it works perfectly, but mind the hacks.</p>
</div>
</body>
</html>
The HTML: We add .valign wrappers around each column. (Give them a more "semantic" name if it makes you happier.) These need to be kept without whitespace in between or else text spaces will push them apart. (I know it sucks, but that's what you get for being "pure" with the markup and separating it from the presentation layer... Ha!)
The CSS: We use vertical-align:middle to line up the blocks to the text baseline of the group-header element. The different heights of each block will stay vertically centered and push out the height of their container. The widths of the elements need to be calculated to fit the width. Here, they are 400 and 100, minus their horizontal padding.
The IE fixes: Internet Explorer only displays inline-block for natively-inline elements (e.g. span, not div). But, if we give the div hasLayout and then display it inline, it will behave just like inline-block. The margin adjustment is to fix a 1px gap at the top (try adding background colors to the .group-title to see).
I would recommend not using a table in this instance, because that is not tabular data; it's purely presentational to have the button located at the far right. This is what I'd do to duplicate your table structure (change to a different H# to suit where you are in your site's hierarchy):
<style>
.group-header { background: yellow; zoom: 1; padding: 8px; }
.group-header:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
/* set width appropriately to allow room for button */
.group-header h3 { float: left; width: 300px; }
/* set line-height or margins to align with h3 baseline or middle */
.group-header input { float: right; }
</style>
<div class="group-header">
<h3>This is my title</h3>
<input type="button" value="Collapse"/>
</div>
If you want true vertical alignment in the middle (ie, if the text wraps the button is still middle-aligned with respect to both lines of text), then you either need to do a table or work something with position: absolute and margins. You can add position: relative to your drop-down menu (or more likely its parent) in order to pull it into the same ordering level as the buttons, allowing you to bump it above them with z-index, if it comes to that.
Note that you don't need width: 100% on the div because it's a block-level element, and zoom: 1 makes the div behave like it has a clearfix in IE (other browsers pick up the actual clearfix). You also don't need all those extraneous classes if you're targeting things a bit more specifically, although you might need a wrapper div or span on the button to make positioning easier.
Do a double float in a div and use the clearfix. http://www.webtoolkit.info/css-clearfix.html Do you have any padding/margin restrictions?
<div class="clearfix">
<div style="float:left">Title</div>
<input type="button" value="Button" style="float:right" />
</div>
<div class="group-header">
<input type="button" name="Button" value="Button" style="float:right" />
<span>Title</span>
</div>
I've chose to use Flexbox, because it made things so much easier.
You basically need to go to the parent of the children you want to align and add display:box (prefixed of course). To make them sit in the sides, use justify-content. Space between is the right thing when you have elements which need to be aligned to the end, like in this case (see link)...
Then the vertical align issue. Because I made the parent of the two elements, you want to align a Flexbox. It's easy now to use align-items: center.
Then I added the styles you wanted before, removed the float from the title and button in the header and added a padding:
.group-header, .group-content {
width: 500px;
margin: 0 auto;
}
.group-header{
border: 1px solid red;
background: yellow;
overflow: hidden;
display: -webkit-box;
display: -moz-box;
display: box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-justify-content: space-between;
-moz-justify-content: space-between;
-ms-justify-content: space-between;
-o-justify-content: space-between;
justify-content: space-between;
webkit-align-items: center;
-moz-align-items: center;
-ms-align-items: center;
-o-align-items: center;
align-items: center;
padding: 8px 0;
}
.group-content{
border: 1px solid black;
background: #DDD;
}
.group-title {
padding-left: 8px;
}
.group-buttons {
padding-right: 8px
}
See Demo
I agree that one should really only use tables for tabular data, for the simple reason that tables don't show until they're finished loading (no matter how fast that is; it's slower that the CSS method). I do, however, feel that this is the simplest and most elegant solution:
<html>
<head>
<title>stack header</title>
<style type="text/css">
#stackheader {
background-color: #666;
color: #FFF;
width: 410px;
height: 50px;
}
#title {
color: #FFF;
float: left;
padding: 15px 0 0 15px;
}
#button {
color: #FFF;
float: right;
padding: 15px 15px 0 0;
}
</style>
</head>
<body>
<div id="stackheader">
<div id="title">Title</div>
<div id="button">Button</div>
</div>
</body>
</html>
The button function and any extra detail can be styled from this basic form. Apologies for the bad tags.