How to make children auto fit parent's width only with CSS? - html

I have a server-side component that generates a fluid layout "toolbar" using DIV without fixed width, generating many A inside it.
Then I need customize that layout to make all A tags auto fit to the parent width. But the number of children is variable and the parent's width isn't known (it auto fits itself to the window).
I made some tests with this Fiddle: http://jsfiddle.net/ErickPetru/6nSEj/1/
But I can't find a way to make it dynamic (uncomment the last A tag to see how it ins't working, lol).
I can't change the server-side sources to gerenate HTML with fixed width. And I really would like to solve it only with CSS if there is any way, even that with JavaScript I could achieve that result.
How can I make all the children auto-fit itself to the parent's width independently of the number of children?

You can use display: table-cell:
See: http://jsfiddle.net/6nSEj/12/ (or with 5 children)
This won't work in IE7 because that browser simply doesn't support display: table and friends.
div.parent {
..
width: 100%;
display: table;
table-layout: fixed;
}
div.parent a {
..
display: table-cell;
}

This is already a pretty old question. Although the answers given attended well at the time, nowadays the Flexible Box Layout offers the same result with much more simplicity, with good support in all modern browsers. I strongly recommend it!
/* Important parts */
.parent {
display: flex;
}
.parent a {
flex: 1;
}
/* Decoration */
.parent {
padding: 8px;
border: 1px solid #ccc;
background: #ededed;
}
.parent a {
line-height: 26px;
text-align: center;
text-decoration: none;
border: 1px solid #ccc;
background: #dbdbdb;
color: #111;
}
<div class="parent">
Some
Other
Any
</div>
<br>
<div class="parent">
Some
Other
Any
One More
Last
</div>

For now many use jQuery as a solution to this problem. All you need is one line. This is from your fiddle.
$("div.parent a").css("width", (($("div.parent").width() / $("div.parent a").length ) -2) + "px");

Related

What to do besides FLEXBOX to make put a stretchable item in between two fixed sized items in a single row on website?

I'm trying to create a header. I have a parent div container with 3 child divs. Child div 1 is fixed and will be aligned to the left. Child div 3 is fixed and will be aligned to the right. Child div 2 has a variable size and will fit in between Child 1 and Child 3. Child 2 will have a size the changes based on browser size (it will expand and shrink to a certain point).
I want my header to be compatible with older versions of IE, at least back to I.E. version 8. I'm reading about FLEXBOXes and looks like it's not even fully compatible with I.E. 11 without bugs.
I'm thinking about using a table but was wondering if there are better ways to do this...as I briefly tested the table and it's not doing what I want either. I tried it and even though I specified a width for each element, when I shrink my browser, the child 1 and child 3 change in size - NOT what I want.
Thanks!
With IE8 you can consider tables, but the old way of doing this is with floats.
#wrapper {
overflow: hidden; /* Establish BFC */
}
#child1 {
float: left;
width: 200px;
background: yellow;
}
#child3 {
float: right;
width: 150px;
background: pink;
}
#child2 {
overflow: hidden; /* Establish BFC */
background: cyan;
}
<div id="wrapper">
<div id="child1">Child 1</div>
<div id="child3">Child 3</div>
<div id="child2">Child 2</div>
</div>
To enforce a single row you can add set max-width percentages to #child1 and #child2 that add up 100%.
I'm not too clear on the problem you ran into when attempting to use tables. Could you explain what the problem was?
You can try to use divs and CSS to create the display as a table. This way you can, for example, use feature queries to see if flexbox is available and use it. If not, you can fallback to using the table CSS below. All without changing the HTML.
Let me know if this works for you!
#container{
display: table;
/* use table-layout: fixed if you're
having problems with the content expanding
the fixed cells */
/* table-layout: fixed; */
width: 100%; /* or however big you need it */
}
#row{
display: table-row;
}
#one,
#two,
#three{
display: table-cell;
}
#one{
width: 100px;
background: blue;
}
#two{
width: auto;
background: red;
}
#three{
width: 100px;
background: orange;
}
<div id="container">
<div id="row">
<div id="one">Div 1</div>
<div id="two">Div 2</div>
<div id="three">Div 3</div>
</div>
</div>
Well, flexbox was created specifically to provide a CSS way to do what you describe, so it's a little like asking how to find the area of a square without multiplying...
Prior to flexbox my go-to solution for this sort of problem was to use JavaScript to dynamically resize the appropriate div (the 2nd child in your case). I really disliked this solution even then because I don't think JavaScript is a good place for layout logic to live, but it was the best I could come up with.
I suppose you could use a table, but I think you'll run into quirky limitations on the layout within the "cells" then.
Here is one solution, but it has limitations. You have to know the width of Child 3 and position your parent div to relative.
https://jsfiddle.net/whatisthebigpicture/sj9xv9m6/1/
header {
position: relative;
}
div {
outline: 1px solid red;
}
.div1 {
width: 100px;
float: left;
}
.div2 {
margin-right: 100px;
}
.div3 {
width: 100px;
top: 0;
right: 0;
position: absolute;
}

Vertically center a textbox in a right-aligned div

One of the solutions I learned is to set the display of the parent div element to table-cell and use the vertical-align property.
While this works, in my case I also need the parent div to float right, but it breaks the table-cell trick and the whole thing does not work now.
So my question is simple: Why exactly is this happening, and more importantly, how can I achieve the effect I want?
div {
/* float: right; uncomment this will make this not working */
display: table-cell;
vertical-align: middle;
height: 60px;
border: 1px solid red;
}
<div>
<input>
</div>
Corresponding JSFiddle
CSS3 provides flexbox. All you need is this:
body {
display: flex; /* create flex container */
justify-content: flex-end; /* align child to right edge */
}
div {
display: flex; /* create nested flex container */
align-items: center; /* center child vertically */
height: 60px;
border: 1px solid red;
}
<div>
<input>
</div>
Benefits of flexbox:
minimal code; very efficient
centering, both vertically and horizontally, is simple and easy
equal height columns are simple and easy
multiple options for aligning flex elements
it's responsive
unlike floats and tables, which offer limited layout capacity because they were never intended for building layouts, flexbox is a modern (CSS3) technique with a broad range of options.
To learn more about flexbox visit:
Methods for Aligning Flex Items
Using CSS flexible boxes ~ MDN
A Complete Guide to Flexbox ~ CSS-Tricks
What the Flexbox?! ~ YouTube video tutorial
Browser support:
Flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, use Autoprefixer. More details in this answer.
Wrap everything with a div set to float:right.
updated your fiddle with few tweaks. hope this works for you.
Please check http://jsfiddle.net/53ALd/3780/
html :
<div >
<input class="form-control" id="txtWOFastNavigation">
</div>
css :
div {
float: right;
height: 160px;
border: 1px solid #000;
position: relative;
background: red;
width: 104px;
}
div .form-control{
width: 100px;
position: absolute;
top: 50%;
transform: translateY(-50%);
}

How do I set a center container to stay responsive?

I have three containers (div), the third div has a set width but I need the other two to be responsive. Current html setup:
<div id="page-type">
<div id="type-container">
<div>
<p id="type-title">Events</p>
</div>
</div>
<div class="type-options">
</div>
<div id="type-back">
Back to Explore
</div>
</div>
Current css:
#page-type {
float: left;
width: 100%;
background: #D2D3D5;
height: 60px;
}
#type-container {
float: left;
width: auto;
}
#type-options {
height: 60px;
width: auto;
overflow: hidden;
}
#type-back {
border-left: 1px #BDBEC1 solid;
float: right;
width: 160px;
}
I can get type-container and type-options to be on the same line and responsive but I can't keep type-back on the same line.
visual example:
----- EDIT -----
To clarify more:
type-container adjusts to fit it's content
type-back is a set width
type-option fills in the space between type-container and type-back regardless of content
type-containerand type-options fill up the whole row pushing type-back to the next line. I need type-back to stay to the right of the line while the other two are responsive.
Put a wrapper around your first two columns and then you can use CSS3's calc().
#wrapper {
width: calc(100% - 161px); /* extra px for 1px border */
float: left;
}
Demo here
IE8 Workaround - Use border-box:
#wrapper {
margin-right: -161px;
padding-right: 161px;
width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
IE8 Demo
In CSS3 you can use calc(X% - 160px) to reduce the width of a percentage based container by a number of pixels.
A quick example could be: http://jsfiddle.net/e3vC4/
There isn't a need to use calc for this, even though its a nice feature to have (+1) — sadly its support is still patchy in places and despite much research it's still difficult to say exactly which browser versions will work as expected (fine if you assume all modern browser users auto-upgrade however).
Depending on what your prerequisites are, you have two other options that I'm aware of:
1. Position absolute the last column
This is a simple solution, however something to be wary of is that certain older mobile devices may treat position absolute in odd ways.
In order to get this to work, all you need to do is place position: relative on your container, and position: absolute; right: 0; top: 0; on your third column... and to keep the centering of your central column correct, add margin-right: 161px.
Pos. Abs. example on JSFiddle
CSS ~ markup is as per your example
#page-type {
display: block;
position: relative; /* added */
width: 100%;
background: #D2D3D5;
height: 60px;
overflow: hidden;
}
#type-container {
display: block;
float: left;
text-align: center;
}
#type-options {
display: block;
height: 100%;
text-align: center;
overflow: hidden;
margin-right: 161px; /* added */
}
#type-back {
display: block;
position: absolute; /* added */
right: 0; /* added */
top: 0; /* added */
border-left: 1px #BDBEC1 solid;
width: 160px;
height: 100%;
}
2. Float right, and/or left, before sibling without hasLayout / shrinkwrap
This works on the basis that a floated element takes up space in the document, and a block element, by default, auto-expands to fill the remaining area that it can — as long as it hasn't been forced to rigidly define its edges with the likes of float, overflow or other hasLayout or shrinkwrap tricks.
This option is only open to you if you can re-arrange your DOM ordering i.e. place #type-back before #type-options. This won't affect the visual order, but it makes a big difference to how the layout is calculated, and is one of the reasons why you were encountering problems with your attempts. You need to have the floated elements in place before leaving the other elements to calculate their dimensions.
Float example on JSFiddle
NOTE: Changing the order of DOM elements can be of benefit, but it can also be a hindrance; it all depends on what the markup is, and who will be viewing it. For example, sometimes having actionable links higher up the DOM can be useful to tabbing and screen-reader users, but the opposite can also be true depending on the context.
MARKUP ~ note the rearranged DOM order
<div id="page-type">
<div id="type-container">
<p id="type-title">Events</p>
</div>
<div id="type-back">
<p>Back to Explore</p>
</div>
<div id="type-options">
<p>Options</p>
</div>
</div>
CSS
#page-type {
display: block;
width: 100%;
background: #D2D3D5;
height: 60px;
overflow: hidden;
}
#type-container {
display: block;
float: left;
text-align: center;
}
#type-options {
display: block;
height: 100%;
text-align: center;
overflow: hidden;
}
#type-back {
float: right;
border-left: 1px #BDBEC1 solid;
width: 160px;
height: 100%;
}
NOTE: It should be stated this version does break on to the next line when "responsed" down to a very minimal size. However, I tend to prefer to design items to disappear when space is tight, and this method lends well to that thinking.
Summary
These are just two other possible options. If you are developing for a progressive client, or yourself, then I personally would stick with the calc method. It's easier to work out what is going on, and far easier for a future developer to change.
However, sometimes often frequently all the blasted time clients want to support the widest range of devices possible (without investing the extra time and money that would be required), and in this instance you are better off with an alternative method (one that isn't going to randomly break on a manager's less than contemporary laptop, running IE 7.5? or 8.33333??? or even Netscape 4.7¿).
Unless of course, you have any leeway to fight for using the more progressive approach, which does seem to be getting easier of late.
I sat down with the designer for more clarification and to discuss alternate solutions. I'm making the third did responsive as well allowing me to use two containers: one holds page-type and type-options set to x% and another holds type-back set to y%. Doing this allows me to keep all elements responsive.

How to position divs in nice little rows

I would like to position 8 divs in the following way:
Here is my JSfiddle which has all the div code: http://jsfiddle.net/XRTh5/
What I would like to do is make the div's behave the same way as on this website with it's icons" http://cyberdust.com/. See how when you re-size the page, the icons shrink and get smaller instead of not changing?
Thanks for the help. I would like to do this only using `div's and not using tables or any old technology like that.
Strongly suggest you look at using a framework to accomplish this just as the reference website uses.
But in general it can be accomplished with css and the #media (min-width: 768px) {}
which applies different css styles when the browser viewpoint/window is resized.
There are a couple but for your specific need they use bootstrap.js http://getbootstrap.com/
Use float: left; to float your items, and percentage based widths for a layout that scales.
Remove heights from your container elements to allow them to expand and fit their contents.
Example: http://jsfiddle.net/XRTh5/37/
The site that you referenced uses media queries to adjust styles based on window width. That would also work, but percentages may be a simpler way of achieving your desired result.
UPDATE: using a neat little trick with percentage-based padding and position: absolute, you can cause the grid items to maintain an aspect ratio. See fiddle link above.
The example website you posted is using breakpoints to set the size of the icons to specific values depending on the size of the users viewport.
read up on media queries and you should be able to replicate this very easily.
You could also set the size of your icons to a percentage value rather than a fixed width or height and this would scale dynamically but will not re-flow very gracefully.
Something else to investigate is flexbox as this will flex to fit the available space quite nicely but isn't 100% supported on all browsers.
Hope this helps
if you don't need the gap in between the the rows then a few simple tweaks to your css will do:
.main {
display:table;
border-spacing:50px;
}
.row {
display:table-row;
}
.icon {
display:table-cell;
}
Example
Otherwise you just need to add and extra closing and opening main div to get the middle gap:
If you do need the gap in the middle
You need to add the following CSS:
* { box-sizing: border-box; } //border will not add to element width
.icon {
width: 25%;
height: 150px;
background-color: orange;
border: 1px solid black;
float: left; //objects will sit next to eachother
}
Also, you way want to set this all up using % values for width/height so that you can get the responsive resizing effect
In answer to your first question, how to make the div, use float:left on the icons to make them fit horizontally.
Use relative width's to make them shrink. To make them shrink and realign perfectly, you need to use media queries, which I'll not go into right now. Here's the updated css
.main {
height: 400px;
width: 100%;/*relative widths*/
background-color: green;
}
.row {
width: 100%;/*relative widths*/
background-color: blue;
}
.icon {
width: 20%;/*relative widths*/
height: 120px;
background-color: orange;
border: 1px solid black;
float:left;/*fit horizontally*/
}
.row{
clear:both;/*To stop the icons from floating*/
}
jsfiddle: http://jsfiddle.net/mDtjP/
I think that is what you need
.row div{
float:left;
}
Just float de divs
http://jsfiddle.net/XRTh5/15/
try this DEMO i change you code
.main {
background-color: green;
display:inline-block;
}
.row {
background-color: blue;
padding:5px;
}
.icon {
width: 200px;
height: 150px;
background-color: orange;
border: 1px solid black;
display:inline-block;
}
You should set float: left like here: http://jsfiddle.net/XRTh5/10/
.icon {
width: 198px;
height: 150px;
background-color: orange;
border: 1px solid black;
float: left;
}
Also remember about decreasing div size to 198px if you want to fit them in 800px (you have 2px border).

how to center text vertically without additional html

I want to know is there a way to centre text vertically without the use of a container element. something which is responsive.
EDIT
the only value I would know is the height of the h3 element, nothing more,
content will appear underneath some as etc
CSS
h3 {
height: 140px;
padding-top: 80px;
min-height: inherit;
border: 1px solid black;
text-align: center;
}
HTML
<h3>TEST</h3>
Here is an example of what i want to achieve
codepen test
Line-height is a beautiful thing, especially if its just text. And if you want to be responsive:
h3 {
background-color: transparent;
height: 40vh;
line-height: 40vh;
min-height: inherit;
border: 1px solid black;
text-align: center;
}
There is no easy way to do this. I have come up with a couple techniques over the years.
You have 80px in padding and a height of 140px for a combined height of 240px. If you know that the text will not exceed one line you can do it using line-height.
h3{
line-height:240px;
...
}
Another way is to use padding if you know the height of your text.
h3{
font-size: 20px;
line-height:20px;
padding:110px 0;/* (240-20)/2 */
...
}
note: I don't like the display: table-cell hack and have yet to need it. Why move away from a table based layout if you're just going to tell the browser to treat the element as a table?
Add to your code:
display: table-cell;
vertical-align: middle;
You will need to adjust your padding. That should work.
This article provides 6 different methods and their associated pros and cons; it explains it far better than I could here. The solutions provided as answers here are good, but the article really covers niche cases and allows you to choose the best method to fit your needs.
http://www.vanseodesign.com/css/vertical-centering/
You're going to have a containing element, regardless. It's just that the body might be the container.
You could do this:
body {
height:100%;
display: table;
margin: 0px;
padding: 0px;
}
h3 {
display: table-cell;
vertical-align: middle;
}
OR...
body {
height:100%;
margin: 0px;
padding: 0px;
}
h3 {
position: relative;
top: 50%;
}
edit - removed width specific styles as it has nothing to do with the solution. Thanks to Jason for the margin/padding set to 0px to remove ugly scrollbars. Jason also noted that this solution did not work for Chrome unless the "body" element in the styles was changed to "html, body", but I was not able to replicate this problem using Chrome version 35.0... For good measure I also opened a test page in Safari and Firefox and they also worked as expected.
edit^2 - Figured out the problem Jason saw. If you use the html5 doctype, then, yes, you will have to include the html element with the body style. This also makes the scrollbar reappear in the relative position solution. So that's fun. I will leave this up for the purpose of saving frustration in the future, but I would check out the link provided in Jason's solution.
http://phrogz.net/CSS/vertical-align/
How can I vertically center text in a dynamically height div?