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

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.

Related

How to make child div fill parent div keeping the parent padding in CSS?

Wanted to know about the trick that would enable a child div to follow the height of parent div "Responsively".
height: 100% covers the padding too. How can I make child fill the "available" space?
Set the box-sizing of the parent to content-box
content-box
This is the initial and default value as specified by the CSS standard. The width and height properties include the content, but does not include the padding, border, or margin.
.parent {
height: 80vmin;
margin: 5vmin;
background: lightblue;
padding: 5vmin;
box-sizing: content-box;
}
.child {
background: rebeccapurple;
height: 100%;
}
<div class="parent">
<div class="child"></div>
</div>

Can a position:absolute element be made sticky?

In CSS, position: sticky enables an element to display with a position: static behaviour (ie. it adopts its default position within the document flow) until it reaches a certain scroll position, after which it adopts position: fixed behaviour.
So... does that mean we cannot use position: sticky on an element which requires a normal behaviour of position: absolute?
Context:
I have an out-of-flow element which occupies a position towards the top-left corner of the viewport. After an inch or two of scrolling, the element hits the top of the viewport and, ideally, I'd like it not to carry on disappearing at that point.
You actually can leverage display: grid and have a sticky element that doesn't pushes its siblings:
header {
display: flex;
align-items: center;
justify-content: center;
height: 50vh;
border: 1px dashed #f00;
}
main {
display: grid;
}
div {
display: flex;
align-items: center;
justify-content: center;
}
.section {
grid-column: 1;
height: 100vh;
border: 1px dashed #0f0;
}
.first.section {
grid-row: 1;
}
.sticky {
grid-row: 1;
grid-column: 1;
position: sticky;
top: 0;
height: 30vh;
border: 1px dashed #0ff;
}
footer {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
border: 1px dashed #f00;
}
<header>I'm the header</header>
<main>
<div class="sticky">I'm sticky</div>
<div class="first section">Just</div>
<div class="section">some</div>
<div class="section">sections</div>
</main>
<footer>I'm the footer</footer>
The trick here is to place the sticky section and its first sibling on the first row and first column of their parent (because grids allow us to place many elements in the same cell).
The sticky element remains sticky in its parent so it will stay on scroll beyond its cell.
As GibboK says, the default positioning scheme isn't absolute positioning, it's the static position. Elements are laid out in normal flow by default — if out-of-flow were the default, then the default HTML page would be impossible to read. Besides, absolutely positioned elements do scroll with the page most of the time — the only time you can make an absolutely positioned behave like a fixed positioned element with respect to page scrolling is through some semi-complicated CSS.
If you're asking whether it's possible for
a stickily positioned element to be out-of-flow when stuck and unstuck, or
for the containing block of a stickily positioned element to be determined the same way as for an absolutely positioned element,
then unfortunately neither of these is supported by sticky positioning.
The point of position:sticky is that it is only fixed while the parent element is not in view. A position:absolute element isn't attached to it's parent.
It could be interesting if such a position would exist and the rule would be that the element would be absolute, while the element it is absolute positioned to is in view, but currently there exists nothing like this nativley, but you could try to recreate it using JS.
A way to make a sticky element look like it's absolutely positioned
I came up with this hack that achieves the goal, but I haven't figured out how to fix its one flaw: There's a blank area at the bottom of the scrollable content equal to the height of the sticky element + its initial vertical offset.
See the comments in the code for an explanation of how it works.
#body {
width: 100%;
position: relative;
background: Linen;
font-family: sans-serif;
font-size: 40px;
}
/* to position your sticky element vertically, use the
height of this empty/invisible block element */
#sticky-y-offset {
z-index: 0;
height: 100px;
}
/* to position your sticky element horizontally, use the
width of this empty/invisible inline-block element */
#sticky-x-offset {
z-index: 0;
width: 100px;
display: inline-block;
}
/* this element is sticky so must have a static position,
but we can fake an absolute position relative to the
upper left of its container by resizing the invisible
blocks above and to the left of it. */
#sticky-item {
width: 150px;
height: 100px;
border-radius: 10px;
background-color: rgba(0, 0, 255, 0.3);
display: inline-block;
position: sticky;
top: -80px;
bottom: -80px;
}
/* this div will contain the non-sticky main content of
the container. We translate it vertically upward by
sticky-y-offset's height + sticky-item's height */
#not-sticky {
width: 100%;
background-color: rgba(0, 0, 255, 0.1);
transform: translateY(-200px);
}
.in-flow {
width: 90%;
height: 150px;
border-radius: 10px;
margin: 10px auto;
padding: 10px 10px;
background: green;
opacity: 30%;
}
<div id="body">
<div id="sticky-y-offset"></div>
<div id="sticky-x-offset"></div>
<div id="sticky-item">absolute & sticky</div>
<div id="not-sticky">
<div class="in-flow">in flow</div>
<div class="in-flow">in flow</div>
<div class="in-flow">in flow</div>
<div class="in-flow">in flow</div>
</div>
</div>

HTML/CSS - Horizontally center a div that is constantly changing in width

I have a parent div (for sake of test we'll call it #parent) and a child div (test reasons #child). #parent is absolutely positioned to the bottom of the page, with a fixed width of 100% and a height of 75px.
child is a div that holds dynamic content (being changed with jQuery). Seeing as it is dynamic, the width of the div is always different. What is the most efficient way to center this div horizontally, since the width is always unknown & different? Any help would be awesome.
The correct way to do this would be the following:
#child {
margin: 0 auto;
}
This sets the top/bottom margins to 0, and then the left/right margins to auto - which means "as large as possible". So you have two equal margins on the left and the right, filling up the space completely, and hence you have a centred div.
This will only work on block elements like divs though - inline elements cannot have auto margins. If you need to centre an inline element (like a span or some text), use text-align: center; on the parent:
#parent {
text-align: center;
}
You could set the margins to: margin: 0, auto;
For fun you could use the CSS Flexible Box Layout Module. Here is a jsFiddle demonstrating what you could do:
See working jsFiddle demo
HTML
<footer>
<div class="dynamic-content">Here is some child dynamic content</div>
</footer>
CSS
body
{
background: #ccc;
}
footer
{
/* As of August 2012, only supported in Chrome 21+ */
display: -webkit-flex;
display: flex;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #232323;
}
footer .dynamic-content
{
flex: 1;
padding: 10px;
margin: 0 auto;
background: #545454;
color: white;
font-family: verdana;
}
Centering a div using CSS:
HTML:
<div class="center">
.... more content ....
</div>
CSS:
.center {
margin: 0 auto;
}
OR
.center {
margin-left: auto;
margin-right: auto;
}
The margin: 0 auto; sets the left and right margin to whatever pixel left on the left and right of the page.
Try in jsfiddle
Make it display as an inline element and give the parent the property of text-align center
problem solved
#parent{
text-align:center;
}
#child{
display:inline-block;
}
Edit:
check how it works http://jsfiddle.net/ECMau/1/

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

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;

css floated element position collapse when resized

Whenever I resize the browser, the 2nd div in .container positions below the first one.
<div class = "container">
<div class = "one"></div>
<div class = "two"></div>
</div>
The divs are really blank.
CSS
.container{
overflow: hidden;
width: 810px;
min-width: 810px;
}
.one,.two{
width: 300px;
height: 450px;
}
.one{float:left}
I just realized that, you are not floating the other element, this is causing it to shift down, you should use float: left; or right as it's a div so it will take up entire horizontal space, and hence it is pushed down.
Demo
.one, .two{
width: 300px;
height: 450px;
float:left; /* Float both elements */
background: #f00;
}
Alternative
You should use display: inline-block; and white-space: nowrap; to prevent the wrapping of the elements
Demo
This will gave you the same effect, the only thing is 4px white space, you can simply use
.two {
margin-left: -4px;
}
the above will fix the white space issue for you
Demo 2
Add this CSS. Demo.
.two {
margin-left: 300px;
}
PS: When works with float, you should clearfix.
Give your body a minimum width:
body {
min-width: 1110px;
}
Then, when the viewport gets smaller than 1110px the scrollbar will appear.
Note: if you add margin, padding or border to the divs, add it to the min-width of the body (or take some extra space).

Resources