CSS: how to have child1 the same height as child2? - css

I have 2 elements and I want the height of 1st element to be equal to the height of 2nd element (this height can vary as this element can contain a picture or a video...).
I tried to encapsulate both of them in the same container, and to set float:left property to child 1 so that the height of the container is equal to child 2 (as floated elements do not add the height to the container).
The height of the container is ok (equal the height of child 2) but I still cannot have the height of child 1 equal to the height of its container.
You can see that is this fiddle (I would like to have the yellow part contained inside the green border, and a scroll bar appear in the yellow part... without using JavaScript):
JSFiddle
<div id='container'>
<div id='child1'>
test1<br>test1<br>test1<br>test1<br>test1
</div>
<div id='child2'>
test2<br>test2<br>test2
</div>
</div>
#container{
border:green solid 5px;
}
#child1{
float:left;
background:yellow;
overflow-y:auto;
}
#child2{
background:blue;
}
Thank you for your help!
Pat

LIVE DEMO
#container{
position: relative; /* needed */
border: green solid 5px;
}
#child1{
position: absolute; /* needed */
background: yellow;
overflow-y: auto;
height: 100%; /* fit parent */
width: 20%; /* note */
}
#child2{
margin-left: 20%; /* note*/
background: blue;
}

Do you mean the container value to be inherited by child 1? If so, child 1 should have a value of height: inherit;

Related

Fixed element bahaviour isn't as expected

I have a case where the fixed element is 'positioned' - in a way - relative to the parent container and not the browser window...
.container {
position: relative;
width: 640px;
margin: 0 auto;
}
.options {
position: fixed;
bottom: 0;
width: 100%;
}
.options button {
float: left;
box-sizing: border-box;
width: 25%;
}
<div class="container">
<div class="options">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
</div>
</div>
The div containing the buttons is fixed, and the bottom offset is set to 0. However, the div is offset a certain distance, and starts at the same horizontal distance as the parent container. Now once I set the left offset value to '0' the element positions itself as expected, starting from the edge of the viewport. So I understand that this isn't actually positioned in relation to the parent container. But why is there an offset initially? I'm guessing the default 'auto' setting computes that left value to something other than zero. But how is this value computed?
Also, another point of confusion arose with how the width value is computed, when the value is 100% vs inherit. I looked up and realized that the difference between the two is that while 'width: 100%' sets the width to 100% of the computed value of the parent element, 'width: inherit' takes up the CSS value of the parent literally and applies that to the element. So in the case of the sample I shared above, while the former will set the width of the div containing the buttons to literally 100% of its own parent's computed width, the latter will set to width to '640px', which is the parent's CSS value. The issue I have is, in the first case, where the width is set in percentages, the element is wider than expected. The computed width appears to be computed from the viewport width i.e. 100% of the viewport, and not the parent element, which is what I expected.
If 'width: inherit' acquires the width of 640px from the parent element, then why is the width inherited from the viewport if width is set to 100%, and not the computed value of the parent. Why is it that in one case, the preceding container is considered as the parent from which the value is inherited, and in the other case the viewport is the parent from which the value is computed?
But why is there an offset initially?
That's the case with position values other than static and sticky (fixed, absolute) they keep their parent offsets.
Demo:
*,
*:after,
*:before {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body * {
padding: 10px;
border: 1px solid;
}
body {
text-align: center;
}
[container] {
position: relative;
width: 120px;
margin: 50px;
padding: 30px;
display: inline-block;
}
[absolute] {
position: absolute;
}
[fixed] {
position: fixed;
}
<div container>
<div absolute>absolute</div>
</div>
<br/>
<div container>
<div fixed>fixed</div>
</div>
As you can see even with position applied, the elements don't suddenly jump around to where they're expected to be. You can try adding left:0 add see how they move.
Width: inherit or 100%; ?
Like i said before:
percentage is relative to the containing block, that changes according to css rules, inherit keyword is relative to the parent element defined in the markup and that never changes with css
Much more accurate MDN explanation
Percentage values that are applied to the width, height, padding, margin, and offset properties of an absolutely positioned element (i.e., which has its position set to absolute or fixed) are computed from the element's containing block.
Demo
[container] {
background: orange;
position: relative;
width: 300px;
height: 100px;
transform: translate(0)
}
[fixed] {
background: red;
position: fixed;
width: 100%;
left: 0;
}
<div container>
<div fixed>fixed</div>
</div>
In this example width:100% is behaving as it should because we changed the congaing block of the fixed element using transform: translate(0)
There's many ways to change the containing block of an element i suggest you read up the MDN article on that.
body have a padding per default. You can add padding: 0 to make your fixed element go as far to the left as possible, or add left: 0 to your fixed .options element.
You shouldn't use fixed width (640px), because you should code with responsiveness in mind.
You shouldn't use float in layout, because it mess up the box size of the object. Only use it on images if you want the text to "float" around the image.
html, body { /* ADDED */
margin: 0;
padding: 0;
}
.container {
position: relative;
width: 100%; /* CHANGED */
margin: 0 auto;
/* ADDED */
min-width: 640px;
}
.options {
position: fixed;
bottom: 0;
width: 100%;
/*left: 0; if you don't want to change the padding for the body */
/* ADDED */
display: flex;
}
.options button {
/*float: left;*/
box-sizing: border-box;
/* width: 25%; */
/* ADDED */
flex: 1 1 auto; /* grow / shrink / auto-adjust in width */
}
<div class="container">
<div class="options">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
</div>
</div>

Child element 100% width of it's parent with overflow: scroll

I'm searching for a solution to get the child element 100% width of it's parent.
The problem: The parent has overflow-x: scroll. Text will insert a scrollbar. Now I want a child to get (the new) width of it's container.
Requirements: Pure CSS solution; no further HTML markup; no fixed width.
width: 100% will set it only to the init state width of the container.
Here is a fiddle: https://jsfiddle.net/y166e3nb/
I know it was told NOT to use more HTML markup, but the chosen answer have some issues, for instance, if you extend the text of the parent, or if you change font-size attribute, the chosen solution will not work, since it's doing a calc with a static 330px!
So I decided to post what I think to be a better solution:
.parent {
background: skyblue;
width: 350px;
overflow-x: auto;
padding: 40px 20px;
}
.parent > .content-wrapper {
display: inline-block;
white-space: nowrap;
min-width: 100%;
}
.parent > .content-wrapper > .child {
background: springgreen;
white-space: normal;
}
<div class="parent">
<div class="content-wrapper">
This is some very very very very very long text to extend .parent div horizontaly, in order to see .child divs extending
<div class="child">
This .child div should extend horizontaly
</div>
</div>
</div>
Instead of putting the text directly into the div .parent, we can create another div involving the text (.content-wrapper in the above example).
Then we can use 'display: inline-block' in this new div, to make it respect its content width, not the parent's one!
...in other words...
By adding display: inline-block to .content-wrapper, it'll force this div to have the width of the largest horizontal content inside it, in our case, the text!
Now if we add our .child div inside our new .content-wrapper, the .child will automatically fill the entire width of the .content-wrapper, even without using 'width: 100%', because every div element have by default 'display: block', which makes them have the width of its parent.
We should also use 'min-width: 100%' in our .content-wrapper, just to prevent it to have a width smaller than .parent's one, in case of text width being smaller than .parent's width.
I wasn't sure if you wanted the child to be the width without scrolling or with scrolling, so I came up with both:
Without Scrolling:
.parent {
background: skyblue;
width: 350px;
overflow-x: scroll;
white-space: nowrap;
padding: 40px 20px;
}
.child {
background: springgreen;
width: calc(100% + 40px);
padding: 0 0 0 20px;
margin: 0 0 0 -20px;
}
<div class="parent">
I'm a wide parent. My text-content will wrap my box.
My child should get my new size as 100% width.
<div class="child">
I would go over the full width if I could.
</div>
</div>
https://jsfiddle.net/y166e3nb/2/
With Scrolling:
.parent {
background: skyblue;
width: 350px;
overflow-x: scroll;
white-space: nowrap;
padding: 40px 20px;
}
.child {
background: springgreen;
width:calc(100% + 330px);
padding: 0 0 0 20px;
margin: 0 0 0 -20px;
}
<div class="parent">
I'm a wide parent. My text-content will wrap my box.
My child should get my new size as 100% width.
<div class="child">
I would go over the full width if I could.
</div>
</div>
https://jsfiddle.net/y166e3nb/3/
The calc() statement in each needs to be 2x the value of the padding.
I'm searching for a solution to get the child element 100% width of it's parent
.parent {
position: relative;
}
.child {
position: absolute;
}
This should fix it. But be aware, the parent width is 350 + 20 left padding + 20 right padding, so the child will only be 390px.

problems with a negative top margin of a relative positioned element (vertical alignment)

I'm trying to align vertically a div inside a container with a height defined. I'm following the guide of http://www.vertical-align.com/, but I'm facing some issues.
According to the website, if I use this css with for this code:
#containingBlock {
height: 200px;
position: relative;
overflow: hidden;
border: 1px solid red;
}
#containingBlock > div {
position: absolute;
top: 50%;
border: 1px solid green;
}
#containingBlock > div > div {
position: relative;
top: -50%;
border: 1px solid orange;
}
<div id="containingBlock">
<div>
<div>
This should be placed in the middle
</div>
</div>
</div>
Fiddle available here
I should obtain a text perfectly in the middle. But this doesn't happen because the top: -50% doesn't work. According to Mozilla dev the top property + % value should be based on the parent's height, which has the same height of its child automatically in this case. But the "automatic wrap height" does not seem to be take into consideration. If I specify a explicit height for the parent div (I mean, the first one nested), everything seems to be ok, but I would like it to take the height of its child automatically! What's wrong with this?
If the height of the block to be positioned is known you can affect the correct positioning with negative margin (i.e 50% of the known height).
If it is not known you can affect it with a CSS transform as follows
-webkit-transform:translate(0%, -50%);
This moves the object vertically half it's own height...and so on
HTML
<div class="containingBlock one">
<div>
This should be placed in the middle
</div>
</div>
CSS
.containingBlock {
height: 200px;
position: relative;
border: 1px solid red;
}
.containingBlock > div {
position: absolute;
top: 50%;
border: 1px solid green;
-webkit-transform:translate(0%, -50%);
}
JSfiddle
here's a fiddle: http://jsfiddle.net/dC22r/4/
you have to set an height to the div that has to be centered then give it top:50% and subtract half his height with a negative margin.

Make content DIV overlap header and footer

I'm having some issues with creating this effect with CSS:
http://i.stack.imgur.com/sMBmg.jpg
Basically, I want my content div to float on top and slightly overlap both the header and the footer elements. I've played around with some absolute positioning but I'm not sure if that's the best way to go. I want a responsive solution that works for all devices and screen sizes. Any suggestions?
Here is one way you could do it.
If this is your HTML:
<div class="header">Header</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
Apply the following CSS:
.header, .footer {
height: 100px; /* not strictly needed... */
border: 1px solid blue;
}
.content {
width: 50%; /* for example... */
height: 400px;
background-color: yellow;
margin: 0 auto;
border: 1px dotted blue;
}
.header {
margin-bottom: -25px;
}
.footer {
margin-top: -25px;
}
.content {
position: relative;
z-index: 1;
}
You can see the demo at: http://jsfiddle.net/audetwebdesign/CNnay/
You set up three block level elements for the header, content and footer.
Apply negative margins to the bottom of the header and the top of the footer to
create the offset effect.
Finally, apply z-index to .content to tweak the stacking order so that the
content block is painted over the footer block.
In this layout, the content block will expand vertically as you add more content.
The results looks like:
You can try position:fixed or z-index:2000 of your div class
i have created this http://jsfiddle.net/RVnU7/1/

How do you vertically align an empty div inside a full height div?

Big picture: I'm trying to make a bar graph made up of discrete units. Each unit will be a div. The bar will grow from bottom to top.
Details: I have a container div that holds all of the unit divs, or blocks. The container has a vertical-align of bottom to do this.
This is what it should look like: https://jsfiddle.net/hpf4h/1/
<div id="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
#container {
height: 100px;
width: 10px;
padding: 1px;
background-color: #00f;
display: table-cell;
vertical-align: bottom;
}
.block {
height: 10px;
width: 10px;
margin: 1px 0px 1px 0px;
background-color: #0f0;
}
That works fine, but I need the container to have a height of 100%. Which makes this happen: https://jsfiddle.net/7n7ZH/1/
I'd prefer to find a way to do this with CSS, preferably not too hacky. I'm already using jQuery for the behavior in my project, so I could use that as a last resort.
Edit: Also, all parent tags also have a height of 100%, including HTML and body.
Make #container's container element display:table like this : https://jsfiddle.net/7n7ZH/2/
html, body { height: 100%; margin:0; }
body { display:table; }
#container {
height: 100%;
width: 10px;
padding: 1px;
background-color: #00f;
display: table-cell;
vertical-align: bottom;
}
.block {
height: 10px;
width: 10px;
margin: 1px 0px 1px 0px;
background-color: #0f0;
}
<div id="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
When you use display:table-cell the browser looks for ancestor elements being display:table-row, display:table-row-group and display:table. If it can't find them, it creates pseudo elements to stand in for them. That's what's happening here.
So when you say display:table-cell; height:100%, that's 100% of the created pseudo element that is display:table. But that pseudo element is only as high as its content, and there's no way in CSS to say "make the pseudo-element have height that's 100% the height of its parent instead".
But it is possible to have a real element be display:table and set its height to 100%, in which case the browser will use that and not create the display:table pseudo element.
Applying display:table-cell; and height at the same time rarely gives the results you'd expect. I see that you're trying to use vertical-align which is probably why you added the table-cell. Try css positioning instead:
Remove display:table-cell; and vertical-align from your container.
Add height:100%; to both the body and html elements so your container has room to grow.
Set the container to position:relative; which will make it the origin of all positioned children rather than the document root (body tag). This will allow you to move your container around without screwing up the child positions.
Add a wrapper around your blocks (you could use ul, li for this rather than divs).
Position the block container as position:absolute; bottom:0;
Here's the code...
#container {
height: 100%;
width: 10px;
padding: 1px;
background-color: #00f;
position:relative;
}
.blockContainer
{
position:absolute;
bottom:0px;
}
.block {
height: 10px;
width: 10px;
margin: 1px 0px 1px 0px;
background-color: #0f0;
}
body { height:100% }
html { height: 100%}#container {
height: 100%;
width: 10px;
padding: 1px;
background-color: #00f;
position:relative;
}
.blockContainer
{
position:absolute;
bottom:0px;
}
.block {
height: 10px;
width: 10px;
margin: 1px 0px 1px 0px;
background-color: #0f0;
}
body { height:100% }
html { height: 100%}
...and here's the fiddle...
https://jsfiddle.net/kPEnL/1/
I'm unable to provide assistance with doing it in the way you have started, but taking your original big picture of trying to make a vertical progressbar, here's an alternative which uses the progressbar in Twitter Bootstrap. In its existing form, it doesn't do vertical progress bars, but this modification does.
I originally suggested using stacked bars, but this doesn't work with the vertical implementation. Instead, I've got a solution which uses CSS gradients to draw the blocks in, but still uses the normal bootstrap progress bar.
.progress.discrete {
background-image: linear-gradient(0deg,
black 0%, green 5%, green 95%, black 100%);
background-size: 100% 10%;
background-repeat: repeat-y;
}
/* Bar is used to cover up the blocks, so make it look like a background */
.progress.discrete .bar {
background-image: linear-gradient(to right, #f5f5f5, #f9f9f9);
}
I assumed you wanted your blocks to be a percentage of the bar height rather than an absolute size - this means I can't apply the gradient to the bar. Instead, it can be applied to the background, and the bar used to cover it up (i.e. set width of the bar to 100-progress%). I've also included an example which uses a fixed block size applied to the bar if that's what you wanted.
http://jsfiddle.net/BHTXZ/3/
It needs a little tidying up, but does the trick.

Resources