I have one requirement, where I need to apply width to the parent element which is equal to the first child element's width. This can be easily achieved using display: inline-block or float: left to the parent element if it has only one child element. But I have more than two child elements in a div. Something like this:
Fiddle
<div class="main">
<div class="first">first</div>
<div class="value">valuevalue</div>
</div>
Right now, If I apply display: inline-block to the parent element, then it is having the width of the second child element.
To not happen this, I tried break-word, word-break css properties on the second child element but still no use.
What I am trying to get is illustrated in the following screenshot:
Some important points:
width of the parent element should be equal to the first child element.
height of the parent element should be equal to sum of all the child elements.
I don't know the width of the first child element.
(EDIT) The first child element has some fixed width and height. I don't know these values.
I want to do this using just css. css3 is welcome. (I know how to do this using javascript)
You can Achieve this easily with CSS3's new intrinsic and extrinsic width values(min-content in this cas), although, it's not supported on IE, so it's not an viable option but I will just post this as it's interesting that we will be able to do that in the future:
http://jsfiddle.net/S87nE/
HTML:
<div class="main">
<div class="first">first</div>
<div class="value">valuevaluevalue</div>
</div>
CSS:
.main {
background-color: cornflowerblue;
width: -moz-min-content;
width: -webkit-min-content;
width: min-content;
}
.first {
width: 50px; /* I don't know this width */
height: 50px; /* I don't know this height */
background-color: grey;
}
.value{
word-break: break-all;
}
I guess in the worst case you could use this for newer browsers and JS for IE and older versions.
Reference:
http://dev.w3.org/csswg/css-sizing/#width-height-keywords
http://demosthenes.info/blog/662/Design-From-the-Inside-Out-With-CSS-MinContent
Ideally, the layout style for a HTML snippet like:
<div class="main">
<div class="first">first</div>
<div class="value">firstvaluevalue</div>
<div class="value">second value value</div>
<div class="value">third valuevalue</div>
<div class="value">valuevalue on the fourth line</div>
</div>
is achievable using the following CSS:
.main {
display: inline-block;
background-color: cornflowerblue;
position: relative;
width: 50px;
}
.first {
width: 50px; /* I don't know this width */
height: 50px; /* I don't know this height */
background-color: grey;
}
.value {
word-break: break-all;
margin: 1.00em 0;
}
as shown in: http://jsfiddle.net/audetwebdesign/tPjem/
However, I had to set the width of .main to that of the .first element in order to get the word-break property to take effect.
The CSS rendering problem here is that you want the width of the .value siblings to be equal to the unknown width of .first, which cannot be done with CSS alone.
CSS rendering is essentially a one-pass top-to-bottom algorithm which means that parent elements cannot inherit values from child elements (tables have a multi-pass algorithm but this won't help in this case). This may change in future versions of CSS, but for the we need to design according to these limitations.
The JavaScript/jQuery solution is to get the width from .first and apply it to .main and bind that to a window re-size action.
In some ways, this problem seems to make sense if .first contains an image which would have an intrinsic height and width. If this were the case, it might make sense to set the width of .main to a reasonable value and then scale the image in .first to fill the width of the .main block.
Without knowing more about the actual content, it is hard to come up with alternatives.
Look at my latest comment for the Fiddle link. I changed some things in the html too. Did set the value div inside the first div to use it's width and added word-wrap to the value div.
.main {
display: inline-block;
background-color: cornflowerblue;
position: relative;
}
.first {
width: 50px; /* I don't know this width */
position: relative;
background-color: grey;
}
.first p {
margin-bottom: 30px;
margin-top: 0;
}
.value {
max-width: 100%;
word-wrap:break-word;
background-color: cornflowerblue;
}
html:
<div class="main">
<div class="first">
<p>first</p>
<div class="value">valuevalue</div>
</div>
</div>
http://jsfiddle.net/jxw4q/12/
Important
this answer may not be useful for you, but can help other user who have a similar problem.
you can have the same look as you desire, but without really stretching the parent height. by using position:absolute; on the second div.
Notice: if the parent don't really stretch, it causes problems.
for example, content that will come directly after the parent, will be showed after the .first element. causing an overlap.
you still can use this for cases where this is the only content in the page, and you want the second div to adjust his width to the first.
(I don't think that this is your case, but maybe it will help other user who might stumble into that question.)
anyway, I think that your only option is to use a Script.
For those who fall under the use-case I've described, Here's a Working Fiddle
HTML: (no changes here)
<div class="main">
<div class="first">First div set the width</div>
<div class="value">second fiv should wrap if bigger then first</div>
</div>
CSS:
.main
{
display: inline-block;
position: relative;
}
.first
{
background-color: gray;
}
.value
{
position: absolute;
background-color: cornflowerblue; /* moved here */
}
I don't think you will be able to achieve it without a little help of javascript. Imagine the the following markup and css :
<div class="main">
<div class="first content">first</div>
<div class="second content">valuevalue</div>
</div>
and then the following css :
.main{
background-color : red;
display: inline-block;
max-width: 50px;
}
.first{
background-color : blue;
}
.second{
background-color : green;
}
.content{
word-break: break-word;
}
Now all you gotta do is to set the max-width of your .main div to be equal to your first element and add the content class to each element. I suppose you are adding your elements dynamically.
I got the solution!!
HTML
<div class="main">
<div class="first">first</div>
<div class="value">valuevalue</div>
</div>
CSS
.main {
overflow:hidden;
width:1px;
display:table;
background-color: cornflowerblue;
}
.first {
width: 50px; /* I don't know this width */
height: 50px; /* I don't know this height */
background-color: grey;
display: inline-block;
}
.value {
word-break: break-all;
}
Working Fiddle
Related link
Related
I can not understand how css works, and it's annoying me. I was trying to do some basic side by side two divs and one div below them.
At first I've learned that I had to give float:left for both side by side divs. For curiosity I did'nt gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Then I gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Question: I didn't gave float:left for third div but it didn't act like the first screen shot. Why?
css code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
float: left;
}
.other-posts {
width: 25%;
background-color: #00ff00;
float: left;
}
.author-text {
background-color: #ffff00;
}
html code:
<div class="container">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
<div class="author-text">author text</div>
</div>
When you use a float, you break the natural box-model behavior of the markup.
Your first floated element has a width of 50%, relative to the parent (1000px) it will take the half of the .container. The second (floated) element will take the next 250px. And here comes the good thing.
The third element, which isn't floated, is also a div, thus a block-level element (so implicitly it will take 100% of the width of its parent). If you set the background-color of your first and second element to a transparent one #0000ff00 and #00ff0000 respectively. You will see your third element is growing behind them.
This is, what I mean with "breaking the box-model". Now, to understand this beter, you could start giving a explicit width to the third element. Let's say: 90%, you will see how the yellow background will reduce itself from the right side.
If you set the width to 50% it will "jump" down, to the second line. It will be even broad as the first element, but two times height. With other words, it will try to fit in the first available space.
To avoid this, in the past, we used the clearfix hack... but since flexbox and css grids are broadly supported, we don't have to rely in floats anymore for this side-by-side layouts.
Float has their own use cases, is not that float sucked, it's just not meant for layout.
For more information on this topic you can check this great article about floats on CSS-Tricks.
Wrap the items you want side by side in another wrapper, then apply flexbox to that wrapper:
.my-flex-wrap {
display: flex;
}
Then remove all the floats. Done.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.my-flex-wrap {
display: flex;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
}
.other-posts {
width: 25%;
background-color: #00ff00;
}
.author-text {
background-color: #ffff00;
}
<div class="container">
<div class="my-flex-wrap">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
</div>
<div class="author-text">author text</div>
</div>
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;
}
Please look at the following: http://jsfiddle.net/ran5000/uZ7dD/
the header div has a fixed height of 40px, I want that the content div will use the remaining height of the screen without scroll and regardless of the screen height.
any ideas?
I generally use position:absolute for this, and then set the top value to start at the bottom of the header.
http://jsfiddle.net/uZ7dD/4/
.content {
background-color: yellow;
position:absolute;
top:40px; bottom:0; left:0; right:0;
}
Do you mean like that?
If so, I've used
position: fixed;
property in CSS.
I'm not sure what the browser support is like for the calc CSS feature, but this would be a good case for it. You can read about it here. You would need to change the height of the content div to height: calc(100% - 40px). This, of course doesn't take into account any space taken up by margin, padding, or border so it will still overflow a bit. If you make sure your divs don't have any of those it works perfectly. Here is my JSFiddle for it.
You can also use position: absolute and set the top value to 40px and the bottom to 0px but your parent element needs to have position: relative set.
Alternatively, you can use JavaScript/jQuery to calculate the required height of the content div and apply it.
For css3 browsers just use:
.content {
width: 100%;
background-color: yellow;
height: -moz-calc(100% - 40px);
height: -webkit-calc(100% - 40px);
height: -o-calc(100% - 40px);
height: calc(100% - 40px);
}
for non-css3 browsers use this workaround,
HTML:
<div class="container">
<div class="header">i am the header</div>i am the <content></content>
</div>
CSS
.header {
width: 100%;
height 40px;
line-height: 40px;
background-color: blue;
}
.container{
height: 100%;
background-color: yellow;
}
Hope I could help :)
In this case, the properties of table elements have some advantage in the fact that they have a lot of positioning power. In this case specifically, table rows and cells will always adjust to fill the table container.
Obviously, you don't want to be using actual table html elements, as that would not be semantic, which is where css comes into the game:
If you put a container/wrapper element around both your header and content, and then set it to be display: table; with 100% height and width it will act as the base table element.
Setting your header and content to display: table-row; will now associate them with that container and allow everything to share the table properties. Setting a fixed height on one will still work, and the other will simply fill the remaining space.
<div class="container">
<div class="header">i am the header</div>
<div class="content">i am the <content></content></div>
</div>
And the css:
.container { display: table; width: 100%; height: 100%; }
.header, .content { display: table-row; }
This approach also has the benefit of being well supported across browsers.
<div id='container'>
<div class='left'></div>
<div class='right'></div>
<div class='clear'></div>
</div>
Given the simple markup above, which can be seen in action here at jsFiddle, how do you get the floated right div to take up the remaining height of its parent container that doesn't have an explicit height? The parent container's final height is determined by the floated left div.
Typically, I solve this issue through Javascript, and fix the heights after the page has loaded. But, there must be an alternative, standard, and optimal method of how this is handled.
I think this is just an inherent issue of structuring a layout this way, so what is the alternative beyond using a <table>?
Can't be done without explicit height on the parent using floats.
You can however use display: table-; and table-cell which mimics the behavior of tables without actually using them:
#container {
width: 200px;
background-color: green;
display: table;
}
.left {
display: table-cell;
width: 30px;
height: 200px;
background-color: red;
}
.right {
display: table-cell;
height: 100%;
width: 30px;
background-color: blue;
}
This way you don't need the clearing element and the two divs will always take up 100% of the height, as long as it's declared.
http://jsfiddle.net/6XagR/4/
I'm trying to set up a div which contains 4 divs. I want to set the width of the container and some of the contained divs to set values but they just seem to take the width of the content.
<html>
<head>
<style>
div {
border: 1px solid #888;
}
.container {
width: 300px;
position: relative;
}
.container div {
display: inline;
}
.div1 {
width: 20px;
overflow: hidden;
}
.div2 {
width: 80px;
overflow: hidden;
}
.div3 {
width: 160px;
overflow: hidden;
}
.div4 {
width: 20px;
overflow: hidden;
position: absolute;
top:0px;
right: 0px;
}
</style>
</head>
<body>
<div class="container">
<div class="div1"><img src="1x1.gif" width="1" height="1"/></div>
<div class="div2"><span>date</span></div>
<div class="div3"><span>text</span></div>
<div class="div4"><span>twistie</span></div>
</div>
</body>
</html>
The result looks like this:
+--+----+----+------------------------+---+
| |date|text| |twi|
+--+----+----+------------------------+---+
Can anyone explain why the left-hand divs are not being set to the required widths?
The reason you can't set the widths is because you are setting display:inline;.
When elements are displayed inline, they cannot have their dimensions specified because the size of the element is determined by the length of the text within it.
By default, <div> tags are set to display:block;. This mode can have its height and width specified, but defaults to being displayed below the preceding block.
There are two ways around this for you:
Use display:block; and float:left; -- This will change the blocks into floating elements, which means that subsequent elements will wrap around them. When used with other blocks, this effectively allows you to line them up. However using float can have other unexpected side-effects, due to the wrap-around effect I described.
Use display:inline-block; -- This is my preferred solution to this question. inline-block is a half-way house mode between block and inline. It allows an element to be treated as inline for the purposes of document flow, but still behave like a block internally, in that it will always be rectanguar and you are able to specify height and width, etc. It does have a few quirks (most notably poor support in IE6), but in general for what you're trying to achieve, it's a much cleaner solution and doesn't have the odd side-effects of float.
Hope that helps.
i think it's because of display:inline style
try this:
<div style='width:100px;overflow:hidden;'>
<div style='float:left;width:20px'></div>
<div style='float:left;width:20px'></div>
<div style='float:left;width:20px'></div>
<div style='clear:both;'></div>
</div>
Change your CSS as follows
.container div {
display: inline-block;
}
When you set the container div to inline, you actively set all of its children to inline as well, you may as well have just been using <span>s.
Here is an example for you to see.
http://jsfiddle.net/Kyle_Sevenoaks/ZwKDb/
.container {
float: left;
width: 300px;
position: relative;
}
.container div {
float: left;
}
Should do the trick. Remove the inline display on the interior divs, and float all the divs left. Then you can specify the widths of the divs and any margins between them.