Centered table-like layout with columns of equal widths using CSS? - html

On a web page, I have a row of submit buttons.
This row of buttons should be centered on the page
Each button should be as wide as the widest button (i.e no fixed/hard-coded button widths).
This is easily done with a <table>, but as people keep telling me those are bad for you, I wondered if this can be done with CSS instead. So, I have tried the display: table and table-cell CSS classes, but either the buttons don't get equal widths, or the longest button's caption gets clipped:
.button-row {
display: table;
margin: auto;
table-layout: fixed;
}
.button-row button {
white-space: nowrap;
display: table-cell;
width: 50%;
}
<div class="button-row" >
<button>Short caption</button>
<button>A much longer caption</button>
</div>
Actually, it does look correct in IE, but not in Chrome and Firefox. Here is a fiddle with both my table- and CSS-attempt:
http://jsfiddle.net/kfwhpre8/
If possible, I would like to get rid of the width: 50% settings, because the number of buttons may vary, but that's easy enough to calculate.

Looking at your fiddle, keep in mind that in the table version the buttons are contained in tds. This is the essence of the problem. It appears using table-cell on buttons directly is problematic. If you don't mind chaniging your HTML you can try:
<div class="button-row">
<div>
<button>Short caption</button>
</div>
<div>
<button>A much longer caption</button>
</div>
</div>
.button-row {
display: table;
margin: auto;
table-layout: fixed;
}
.button-row>div {
display: table-cell;
width: 50%;
}
.button-row button {
width:100%;
}
Fiddle

prob not the answer you are looking for as you said you want to get rid of the width:50%
If you set the width:100% in the button-row button{}all the buttons will be as wide as the widest button
.button-row button {
display: table-cell;
width: 100%;
}

I'm unsure if this would suffice, as you'd have to check each time a new button was added, as to the best size for them. But you could simply add a width to each button and a margin to replicate the table layout.
At least in the HTML's current form.
.button-row button {
display: table-cell;
width: 150px;
margin: 1px;
}
Fiddle: http://jsfiddle.net/kfwhpre8/3/

Related

How to stop 3 images side by side inside a div from wrapping to the next line?

I cannot figure this out. I would like 3 images to sit side by side inside a 930px wide div.
so, when you enter into responsive design mode, or drag the screen browser width wise to make it smaller all the 3 images stay side by side inside the div without wrapping to the next line.
But automatically start to re-size to fit the re-sized div.
The 3 images only start to resize correctly inside the div only when the 3rd image has wrapped under the second image. So it looks like this below.
[]
[]
[]
Once all the images are vertically aligned the images then start to shrink down correctly. But this image wrapping under the next image is no good for me, as when viewing the website on a mobile phone, or when re-sizing the screen the images are still super large.
Must be a way to stop these images from wrapping underneath each other, and just stay inline but automatically re-size themselves
as the div/page width shrinks down?
I've tried white-space: nowrap; display: inline; inline-block; even display: table-cell; nothing seems
to do what I need it to do. However, if I use only one image instead of 2, or 3 then it works perfectly fine.
You're probably thinking why not just put all 3 images inside 1 image in photoshop? Well each img is an href link, so that's not possible.
Even floating the images all to the left still doesn't help.
Here's my CSS/HTML
img {
max-width: 100%;
height: auto;
}
then
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="camera.png"> <img src="lights.png"> <img src="action.png">
</div>
Can someone tell me where I may be going wrong please? How can I stop images wrapping underneath other images when the parent container shrinks down.
I've had to resort to using multiple #media queries of different pre-fixed image sizes per break-point. But there's got to be a much much easier way. Something so simple that I'm missing.
I figure I might share a flexbox solution as well. I've included the code below so it should be relatively self explanatory. Feel free to leave a comment below if you think I should clarify anything.
.container{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
img {
flex: 1;
max-width: 100%;
height: auto;
max-height: 310px;
}
<div class="container" style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="https://cdn.vox-cdn.com/uploads/chorus_image/image/44336734/fujifilmx100t-1.0.0.jpg">
<img src="https://d3k7s9wfq6lao0.cloudfront.net/latest/37504/main/7.jpg">
<img src="https://upload.wikimedia.org/wikipedia/commons/3/33/Clapperboard%2C_O2_film%2C_September_2008.jpg">
</div>
you can use inline-block for this. you will need to alter the width with media queries as your screen gets smaller
img {
display:inline-block;
width: 33%;
height: auto;
}
you should also wrap the images in a div.container and give this div a width:100%
Image width set to 100% occupy all the horizontal space of the container, since you want to fit three images inline to each other, divide the 100% by 3 so that when the container is resized the three images will occupy one third of the available space. The margin-left: -2px is to make sure that the image border don't touch the edge, otherwise it will wrap to new line. Try this sample:
CSS:
img {
display: inline-block;
width: 33%;
height: auto;
margin-left: -2px;
box-sizing: border-box;
}
HTML element:
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="camera.png">
<img src="lights.png">
<img src="action.png">
</div>
My answers' more or less a follow up to Tom's which I'm writing on here so I don't overflow the comments section.
The problem with max-width: 100% is that the relative sizing doesn't start to kick in until each image outgrows its parent, in this case, the div. Since all images have a default absolute size based on their image src they force themselves onto a new line before resizing and so only then will max-width start doing what you want it to. As per Tom's response, the percentage sizing of 33% forces the images to have a relative size which causes them to shrink immediately.
Naturally 'img' tags are given the display of inline which means you could opt to just use the following code:
img {
width: 33.3%;
}
Now here's the biggest gotcha I had when dealing with inline images.
A display of inline and inline-block is respective of the whitespace
that exists within your HTML markup.
Therefore the small presence of whitespace below whilst not evident is enough to cause images to still move over to a new line.
img {
width: 33.3%;
}
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="https://picsum.photos/250/250/?random1">
<img src="https://picsum.photos/250/250/?random2">
<img src="https://picsum.photos/250/250/?random3">
</div>
But once this whitespace is removed the images all fit perfectly across the screen whilst resizing.
img {
width: 33.3%;
}
<div style="width: 930px; max-width: 100%; border: 1px solid blue;"><img src="https://picsum.photos/250/250/?random1"><img src="https://picsum.photos/250/250/?random2"><img src="https://picsum.photos/250/250/?random3"></div>
Now compressing the HTML markup above makes it rather unwieldy and so as an alternative, you could opt to use the floating method. By setting a float of left for each image you'll force each 'img' tag to sit flush, regardless of the extra spacing between them. Just be sure to give the parent div a float of left as well or an overflow of auto to stop it from collapsing.
img {
width: 33.3%;
float: left;
}
After many days testing various ways out here's the perfect way to do this without flex. Make sure each image is wrapped in its own div that's important.
<style>
* {
box-sizing: border-box;
}
img {
width: 100%;
max-width: 100%;
height: auto;
}
.column {
float: left;
width: 33.33%;
padding: 5px;
}
/* Clearfix (clear floats) */
.row::after {
content: "";
clear: both;
display: table;
}
</style>
Now, here's where I've changed it up a little bit for more flexibility. Since each image is now in its own div we can then make the image width: 100%; or max-width: 100%; then add the width: 33.33%; part that used to be under img {} to each of the new 3 div columns instead.
<div class="row">
<div class="column"> /* 33.33% width */
<img src="flash-tooltip.png">
</div>
<div class="column"> /* 33.33% width */
<img src="html-tooltip.png">
</div>
<div class="column"> /* 33.33% width */
<img src="portables-tooltip.png">
</div>
</div>
Lot's of people provided great advice.
The easiest way is using flex. But, something people don't tell you when using flexbox. You should still wrap each of the images inside their own div container. Otherwise, you will get some weird things happening when you encase them in hyperlink anchors, that is if all three images are just placed inside the first flex container div. And without their own div container images won't keep any kind aspect ratio when they shrink/enlarge. They just squash and skew together.
And finally very important! Always make sure any images inside a flex container is set up the same way. Either width: 100%; or max-width: 100%; otherwise, the images will not shrink up/down at all in Google Chrome.
I've included this same method as above, only this time in a flexbox version.

How can I specify an element's width as the most it can be without causing a newline break?

I'm quite new to CSS. I'd like to display a long line of text overflowing with ellipses. This jsfiddle demonstrates a working example.
However, note that if you extend the window, the text remains limited at 100px (due to the max-width: 100px) attribute. If I remove the max-width attribute, though, the text never shrinks:
I'd like the text to extend as much as possible without causing a line-break. i.e. this is how it should look for the various window widths:
How would I go about doing this?
this will do the trick.. you can use display: block; instead of display: inline-block; then add margin-right: 75px; so that the text will not overlap the button.
.one-line-only {
font-family: monospace;
display: block;
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 75px; /*(you can set the value depends on your needs)*/
}
then add this css on your button, then add margin-top: -20px; to inline the button.
.b{
margin-top: -20px; /*(you can set the value depends on your needs)*/
float:right;
}
<span class="one-line-only"> Stuff to the left ---- Thisisareallylongthingwhichshouldbestoppedatsomepointforsure</span>
<button class='b'>Stuff right</button>
JSFIDDLE DEMO

display: table-cell same space for all cells

i've got a problem with display: table-cell; and the space between the cells. I'd like to have dynamically the same width for all cells.
See JSFiddle
How you can see the "Ausstattung & Skizze" is much wider than the others. Is there a way to dynamically set the same width to all cells?
You can use table-layout:fixed; on the parent element which holds display:table;
ul{
display: table;
width: 700px;
table-layout: fixed;
}
This way, every cell will get the same width if you don't force their width, no matter how many cells you have in a row.
(Edit: see this JSfiddle http://jsfiddle.net/m8evqnv0/ )
li {
display: inline-block;
width: 150px;
}
edit: no need for inline-block, with width:25%
if the width of the unordered list is fixed, then:-
li
{
width: 25%;
}
best practice:- use classes for li and then style the class.
if you want the table to be responsive, use table markups then. it will work like a charm.
fiddle:- http://jsfiddle.net/4wsmx8t0/3/

HTML Inline-Block DIVs Not Lining Up

So I am designing a website right now (pretty nooby at HTML and CSS) but I made a design on Photoshop beforehand so that I could go right through the coding and make the website how I wanted. Well I have an issue. I have two DIV elements inside of a bigger container DIV that won't line up side-by-side, despite using inline-block. Here is the css code:
.contentContainer {
display: block;
width: 700px;
height: 250px;
margin: 20px auto;
}
.topContainer {
height: 230px;
padding: 10px;
background-color: white;
}
.topThumbnail {
display: inline-block;
width: 370px;
height: 230px;
}
.topThumbnail img {
width: 370px;
height: 230px;
}
.topInfo {
display: inline-block;
margin-left: 10px;
width: 300px;
height: 230px;
}
.topInfo p {
width: 300px;
height: 230px;
background-color: pink;
}
The contentContainer is the highest DIV holding my topContent and topThumbnail so I thought I'd throw it into the provided code.
And the HTML code:
<div class="topContainer">
<div class="topThumbnail">
<img src="YT.png" />
</div>
<div class="topInfo">
<p>Testing the information area of the top container or something along those lines</p>
</div>
</div>
Can't post pictures to explain the issue.. need 10 reputation.. will make it hard to describe.
In the design the two containers for the Thumbnail and the Info are supposed to be side-by-side and aligned at the top. The thumbnail is supposed to be on the left of the topContainer and the Info is supposed to be to the right of the thumbnail with a margin of 10. For some reason the info is not going to the right-side of the thumbnail but rather going under it. I have ALREADY set the margin to 0 to fix the default margin issues.
display: inline-block is working correctly in your example. What you need to add is vertical-align: top to your .topInfo div, and get rid of the default margin on your .topInfo p tag. Also, you need to make sure that there is enough room for the .topInfo div to sit to the side of the .topThumbnail div, otherwise it will wrap to the next line.
Like this:
http://jsfiddle.net/hsdLT/
A cleaner solution: I would look at ditching the display:inline-block CSS proporties on these elements altogether and just float them to the left. Then clear the floats by assigning clear:both to the .topInfo css property.
It's less code then your route will be and it's more structurally sound. :D.
.topThumbnail,
.topInfo {
float:left;
}
.topInfo {
clear:both;
}
Other people have already answered this with the solution, but I think it is important to understand why inline-block elements behave this way. All inline, table, and in this case, inline-block elements have the vertical-align property. The default value is set to baseline, hence the need to set vertical-align: top;.
See the docs here: https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align.
This other discussion is also helpful: Vertical alignment for two inline-block elements not working as expected

Label and input layout using css

I'm trying to line up a label and an input box on the same line in such a way that the label takes up all the space it needs and then the input box uses all of the remaining space. For example if the container was 1000px and the label was 342px then the input should be 658px wide. But if the label changed to 100px the input should resize to 900px. I could do this using a table layout, or using JavaScript to resize the input box when the label width changes but ideally I would like to do this using only css. My html looks like this.
<div id="container">
<label for="inputBox">variable text</label>
<input type="text" id="inputBox" />
</div>
Thanks,
Edit: To help illustrate what I'm trying to do here is an example using tables.
<table style="background-color:#ddd;width:500px;">
<tr>
<td style="width:0;white-space:nowrap;"><label style="width:100%">text</label></td>
<td><input style="width:100%" type="text" /></td>
</tr>
</table>
The correct way would be:
#container { width: 1000px; display: table }
#container label { display: table-cell; white-space: nowrap; }
#inputBox { width: 100%; display: table-cell; }
but that won't work in IE 6 or 7.
#container { margin-left: 100px; position: relative; }
#container label { position: absolute; left: -100px; }
#container input { width: 100%; }
(You can use box-sizing and its browser-specific versions to make sure the borders of the input line up nicely if necessary, and if you need that in IE6-7 too, a bunch of padding hacks to accomodate the extra pixels.)
This requires that the size of the label be known. It can't be made to depend on the width of the text content of label (ie ‘shrink-wrap’) without a bunch of extra markup (which wouldn't really be any better than using tables).
When liquid-layout forms get any more complicated than this, you do typically need to go to tables. Traditional CSS positioning isn't great at distributing widths between fixed, liquid, and shrink-wrap contents.
This CSS should work:
#container { width: 1000px; white-space: nowrap; }
#inputBox { width: 100%; }
Of course you can adjust the width of the container to suit your needs.
EDIT:
The above CSS expands the inputBox to be 1000px and therefore makes the div width greater than wanted.
To achieve the effect you want you can use the overflow property as described in http://www.stubbornella.org/content/2009/07/23/overflow-a-secret-benefit/ and a bit of an additional markup:
<div id="container">
<label for="inputBox">variable text</label>
<div><input type="text" id="inputBox" /></div> <!-- Notice the input is wrapped in an additional div -->
</div>
The CSS:
#container { width: 1000px; white-space: nowrap; }
#container label { float: left; margin-right: 5px; /* The label must be a floating element, the margin adds a little space to visually separate it from the input field */ }
#container div { overflow: hidden; /* This does the trick */ }
#inputBox { width: 100%; }