I need to make a child div leak the parent container max width.
Now, i can only leak parent padding (knowing it).
I need this to wrap all the page on a container and make some sections leak.
Without this, i will need to set the container on every section.
Here is some snippets
Better snippet on codepen
.container {
max-width: 500px;
margin: 0 auto;
padding: 0 30px;
background: lightblue;
}
.child {
background: lightcoral;
height: 200px;
}
.child.cancel-padding {
margin: 0 -30px;
}
.child.leaked {
}
html,
body {
margin: 0;
padding: 0;
}
* {
text-align: center;
font-family: sans-serif;
}
<small>note: see in fullscreen or on codepen</small>
<h1>what i have</h1>
<div class="container">
<div class="child">A element inside a container</div>
</div>
<h1>what i need</h1>
<div class="container-leaked">
<div class="child leaked">
a element inside the container, but leaking all view width (100vw)
</div>
</div>
<h1>what i can do now</h1>
<div class="container">
<div class="child cancel-padding">Make the element cancel the parent padding, that's all</div>
</div>
<h1>Why i need</h1>
<p>
i will wrap all the page in the container, but sometimes i need sections to leak the container with full view width.
</p>
Note: on the demo, i've set the child height, but i will not have control of it. it's a dynamic content div, so height is dynamic.
You can do it by using relative positioning. Indeed, you need position: relative on your container and your child -leak. Then, to center your child, you use
left: 50%;
transform: translateX(-50%);
This works because your container is centered. So left: 50% will move the child left edge to 50% of its parent width from its initial position (which mean the center of its parent). Then, transform: translateX(-50%) will move the left edge of your child 50% of its width on the left. You then just need to add width: 100vw to make your child full width. Here is the snippet:
.page {
position: relative;
}
.container {
max-width: 100px;
margin: 0 auto;
padding: 0 30px;
background: lightblue;
position: relative;
}
.child-leak {
height: 200px;
background: lightcoral;
position: relative;
left: 50%;
transform: translateX(-50%);
padding: 10px;
width: 100vw;
}
html, body{
margin: 0;
padding: 0;
text-align: center;
font-family: sans-serif;
}
<div class="page">
<h1>My title</h1>
<div class="container">
<div class="child-leak">
My full width child
</div>
</div>
<div>Below content</div>
</div>
This technique for horizontally center an element works also for vertical centering. This works because a value in % for top, left, right and bottom refers to the first non static parent width and height. On the other hand, translate with a value in % use the element width and height.
This may be a little bit of a hack, but I've done it before by adding ::before and ::after. Add position: relative to the .child and then add the following css
.child.leaked:before{
content:"";
display: block;
position: absolute;
height: 100%;
width: 100%;
left: -100%;
background-color: red;
top: 0;
}
.child.leaked:after{
content:"";
display: block;
position: absolute;
height: 100%;
width: 100%;
right: -100%;
background-color: red;
top: 0;
}
Here is an approach you can try:
.container {
max-width: 500px;
margin: 0 auto;
padding: 0 30px;
background: lightblue;
}
.child {
background: lightcoral;
height: 200px;
width: 400%;
margin-left: -150%; /* (width of child - 100) / 2 */
}
html,
body {
margin: 0;
padding: 0;
overflow: hidden; /* prevent horizontal scroll bar */
}
* {
text-align: center;
font-family: sans-serif;
}
<div class="container">
<div class="child">I am outside the parent</div>
</div>
Related
This question already has answers here:
CSS margin terror; Margin adds space outside parent element [duplicate]
(7 answers)
Closed 3 years ago.
The row div has a top/bottom margin of 10px (margin: 10px 2px). However, the 10px is pushing the position of the main container. What I am trying to achieve is the row has a top/bottom margin inside the main-container. The margin is some how escaping and pushing the main-container.
Here is my code:
body {
padding: 0;
margin: 0;
}
.main-container {
position: relative;
display: block;
width: 183px;
height: 101px;
background-color: red;
}
.row {
position: relative;
display: block;
margin: 10px 2px;
width: 175px;
height: 15px;
background-color: green;
}
<div class="main-container">
<div class="row">
</div>
<div class="row">
</div>
</div>
But if you run this code (below), without the row div. You can see the position of the main-container is different. This is the position the main-container should be in.
body {
padding: 0;
margin: 0;
}
.main-container {
position: relative;
display: block;
width: 183px;
height: 101px;
background-color: red;
}
<div class="main-container">
</div>
How can I fix this?
You should change your position in the .main-container class to be position: absolute instead of position: relative.
Relative positioning will move the element with the flow of the page, whereas absolute positioning will essentially lock it in whatever position you set it to be in. Relative positioning is more for situations like your .row class, where you want it to depend on the positioning of the .main-container class. Absolute positioning should be used when you don't want other elements (specifically the parent element) to determine it's position.
body {
padding: 0;
margin: 0;
}
.main-container {
position: absolute;
display: block;
width: 183px;
height: 101px;
background-color: red;
}
.row {
position: relative;
display: block;
margin: 10px 2px;
width: 175px;
height: 15px;
background-color: green;
}
<div class="main-container">
<div class="row">
</div>
<div class="row">
</div>
</div>
This article does a great job of explaining why you are having issues when both the parent and child have position: relative. If you take the position off of the parent entirely, you won't even notice a difference. Why? Because there's nothing to position it relative to. If you remove it from the .row class, you will find the same results. Relative positioning looks for an element that has a positioning other than static. In this case, there isn't one, so it's not really doing anything since all of the parents (body, html, etc) have position: static by default.
body {
padding: 0;
margin: 0;
}
.main-container {
display: block;
width: 183px;
height: 101px;
background-color: red;
}
.row {
position: relative;
display: block;
margin: 10px 2px;
width: 175px;
height: 15px;
background-color: green;
}
<div class="main-container">
<div class="row">
</div>
<div class="row">
</div>
</div>
<div class="main-container">
<div class="row">
</div>
<div class="row">
</div>
</div>
body {
padding: 10px;
margin: 0;
}
.main-container {
position: relative;
width: 183px;
height: 101px;
background-color: red;
}
.row {
position: relative;
left: 50%;
top: 35%;
transform: translate(-50%, -50%);
margin: 10px 0;
width: 175px;
height: 15px;
background-color: green;
}
Check it out in https://codepen.io/3rdsty4bl00d/pen/OGbENg?editors=1100#0
I have a simple HTML document with a height of 100vh. The element contains a title. Now when I scroll nothing happens as expected. What I need is an effect that the page stays the same and my title is scrolling up and out of the viewport. How can I achieve that?
My code simplified:
html,
body {
margin: 0;
padding: 0;
}
#wrapper {
background-color: red;
height: 100vh;
width: 100%;
}
h1 {
color: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div id="wrapper">
<h1>Title</h1>
</div>
You can do it the opposite way - not fixing the to-be-scrolled element, but the contents element which you put into the background by using a negative z-index:
Apply position:fixed to the wrapper and move it to the background with z-index: -1. Erase position: absolute from the h1 to reset its position to static to allow it to scroll.
For the scrolling to be possible, you either need enough height for the title element (at least 150% or more), or another (possibly invisible) element that follows afterwards, like in my example below.
The text centering inside h1 can be done via flex (see below).
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
#wrapper {
position: fixed;
z-index: -1;
background-color: red;
height: 100vh;
width: 100%;
}
h1 {
color: white;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
margin: 0;
}
.something_else {
height: 100%;
}
<div id="wrapper"> wrapper contents here... </div>
<h1>Title</h1>
<div class="something_else"></div>
I'm trying to center a text div on top of box div that has inline block. I tried using position: absolute on the text div. But when the browser screen is shrunk or expanded, the positioning of the text div gets messed up. How to fix this?
.mainDiv {
margin: auto;
width: 100%;
padding: 10px;
left: 300px;
text-align: center;
}
.box {
background-color: red;
width: 100px;
height: 100px;
display: inline-block;
}
.text {
background-color: blue;
position: absolute;
top: 70%;
left: 45%;
}
<div class="mainDiv">
<div class="box"></div>
<div class="text">text</div>
</div>
I assume you are using inline-block to center the .box inside the .main-div. Technically, with your current html structure you can't center the .text element on the .box one, but you can center it on .main-div, which is essentially the same thing in your example.
I would start by adding position: relative to .main-div. An absolutely positioned element is positioned based on it's nearest ancestor that has a positioning context. The easiest way to set this is to add position: relative.
Then with your .text element you can adjust to:
.text {
background-color: blue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50% );
}
This works because top and left position the top and left element from the top and left of its parent. So the top of .text would start 50% of the way down .main-div, and likewise with left. This would leave your text too far down and to the left.
transform: translate values work differently - they are based on the size of the element itself. So -50% will move an element back half of its width or height. By setting it on both width and height we are moving the .text so that instead of its top and left edges being at 50%, it's center is at 50%.
.mainDiv {
position: relative; /* added to make .text align relative to this, not the document */
margin: auto;
width: 100%;
padding: 10px;
/* left: 300px; (I removed this for demo purposes, but if you need it you can add it back in) */
text-align: center;
}
.box {
background-color: red;
width: 100px;
height: 100px;
display: inline-block;
}
.text {
background-color: blue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50% ); /*pull the text left and up 50% of the text's size*/
}
<div class="mainDiv">
<div class="box"></div>
<div class="text">text</div>
</div>
The markup for text should be written first then the box. Then you may try using block instead of inline-block, then set the width of the text to 100 percent, display block and 'margin: 0 auto'. Also, maybe consider using the appropriate semantic tags as opposed to divs if you can. Also, I suspect the top and left rules to be causing the text to not align properly. You should no longer need position:absolute either.
If you want, you can make the blue div a child of the red div so that the blue div will always be relative to the red div. I also added position:relative to the red div, and used transform:translate to the blue div.
If I'm not mistaken, this is also responsive, so try shrinking your browser.
.mainDiv {
margin: auto;
width: 100%;
padding: 10px;
left: 300px;
text-align: center;
}
.box {
background-color: red;
width: 100px;
height: 100px;
display: inline-block;
position:relative;
}
.text {
background-color: blue;
position: absolute;
left: 50%;
transform:translate(-50%, -100%);
}
<div class="mainDiv">
<div class="box">
<div class="text">text</div>
</div>
</div>
.mainDiv {
text-align: center;
}
.box {
background-color: red;
width: 100px;
height: 100px;
display: inline-block;
margin-top: 19px;
}
.text {
background-color: blue;
position: absolute;
margin: -19px 0 0 36px;
}
<div class="mainDiv">
<div class="box">
<div class="text">text</div>
</div>
</div>
The last two days I've been reading most questions here and a lot more about 'fill remaining width' and 'escaping overflow: hidden', but I can't get my problem solved. At the moment, I seriously doubt if it is possible at all.
I have a scrolling box with full body width. On top of that I have a absolute positioned header that I need to make the exact same width as the scrollbox. My intention is to make the header 0px or (if needed) 1px in height and let the content overflow.
Here is a fiddle.
The scrollbox has a scrollbar (always visible), the header obviously not. To compensate for that, I float a fake scrollbar to the right inside the header container, and left of that a <div> filling the remaining width (being exactly the innerwidth of the scrollbox).
HTML
//THE SCROLLBOX
<div id="scrollbox">
<div id="center2">
content<br>content<br>...
</div>
</div>
// THE HEADER
<div id="header_box">
<!--- FAKE SCROLLBAR -->
<div id="scroller">
<div></div>
</div>
// REMAINING WIDTH
<div id="container">
<div id="FIRST">
<div id="FIRST_banner"></div>
</div>
</div>
<div id="SECOND">
<div id="SECOND_banner"></div>
</div>
</div>
</div>
CSS
#header_box {
background: yellow;
position: absolute;
left: 0;
top: 0;
right: 0;
height: 25px;
width: 100%;
overflow: visible;
}
#scroller {
float: right;
overflow-x: hidden;
overflow-y: scroll;
height: 50px;
width: auto;
/* visibility: hidden; */
}
#scroller>div {
width: 0px;
height: 101%;
}
#container {
display: inline;
width: auto;
height: 50px;
overflow: visible;
}
#FIRST {
position: relative;
overflow: hidden;
height: 25px;
background: pink;
}
#FIRST_banner {
position: absolute;
top: 0;
left: 50%;
height: 220px;
width: 30px;
background: crimson;
}
#SECOND {
background: darkcyan;
position: relative;
height: 5px;
}
#SECOND_banner {
position: absolute;
top: 0;
left: 50%;
height: 220px;
width: 30px;
background: blue;
}
The problem lies in the div (#FIRST) with remaining width. From all the solutions I've read only the one with
position: relative;
overflow: hidden;
works for me. It gives the exact width, lining up the center of the header and the scrollbox nicely. But I can't break out of the overflow: hidden, so it cuts off the content.
So my second thought was: wrap #FIRST in a #container and let the child determine the width of the parent. After that, I can put another div (#SECOND) inside the container with the width of the parent. It works partially. The #container has the width intended, and the #SECOND div overflows nicely but takes on the width of #header_box, as no width is set on the parent itself.
So, my questions:
Can I somehow break out of the overflow: hidden of the FIRST div? (In that case the container and second div can be removed).
Is there a way to let the SECOND div obey the width of it's parent.
Some totally different solution.
Sadly there is a catch to this all:
css only
no javascript
no flexbox
Thanks voor any toughts.
In the end, it was the good old <table> that saved the day, much simpler than I tought. There still is a fake scrollbar, but the absolute header now aligns perfect with the contents of the scrollable div behind it, and it remains fluid.
See fiddle here
HTML:
<!--- HEADER -->
<div id="THIRD">
<div id="THIRD_A">
<div id="THIRD_B"></div>
<div id="THIRD_C"></div>
<div id="THIRD_D"></div>
</div>
</div>
<!--- FAKE SCROLLBAR -->
<div id="scroller">
<div></div>
</div>
</div>
CSS:
/* The container for the header */
#header_box{
position: absolute;
left: 0;
top: 0;
right: 0;
height: 0px;
width: 100%;
overflow: visible;
display: table;
}
/* Takes on the width of its child: the fake scrollbar */
#scroller {
display: table-cell;
float: right;
overflow-x: hidden;
overflow-y: scroll;
height: 0px;
width: auto;
}
/* This triggers a scrollbar to be shown */
#scroller>div {
width: 0px;
height: 101%;
}
/* The 'remaining width' container (= screenwidth - scrollbar, equals innerwidth of scrollbox) */
#THIRD{
display: table-cell;
width: 100%;
height: 0px;
}
/* Needed to give the children a 'width' reference */
#THIRD_A{
position: relative;
width: 100%;
height: 0px;
}
/* The actual header items */
#THIRD_B {
position: absolute;
top: 0;
left: 50%;
width: 25px;
height: 220px;
background: black;
}
#THIRD_C {
position: absolute;
top: 0;
left: 10%;
width: 125px;
height: 120px;
background: black;
}
#THIRD_D {
position: absolute;
top: 0;
right: 0%;
width: 25px;
height: 220px;
background: black;
}
NOTE:
On most handheld browser, this is 1px off. It seems webkit based browsers display a tablecell of 0px width as 1px width (see this question). The solution is to wrap the table in another div with css:
position absolute;
left: 0;
right: -1px
and setting #scroller>div to a width of 1px.
NOTE 2:
This is also a solution for a fixed div inside a scrollable div. See this fiddle
html:
<div id="main">
<div style="position: absolute; height: 150px; width: 400px; left: 290px;"><img src="HEAD-IMAGE.jpg" /></div>
<div style="position: absolute; height: 300px; width: 233px; top: 180px;"><img src="LEFT-IMAGE.jpg" />(below head)</div>
<div style="position: absolute; top: 200px; left: 270px;">TEXT (next to left image)</div>
</div>
css:
div#main{
position: absolute;
top: 141px; left: 50%;
height: 100%; width: 960px;
padding: 10px;
margin-left: -490px;
text-align: justify;
background-color: yellow;
}
my padding from #main works for my images but not for my text (right & bottom padding).
Why is this happening?
In your example, only the text div has a top and left property. The two divs containing the images only contain one of these properties:
The header div has left: 290px;, so it gets its y-axis position moved by the top padding.
The left div has top: 180px; so it gets its x-axis position moved by the left padding.
The text div has top: 200px; left: 270px; so its x and y-axis are not affected by the padding.
To illustrate this, for this example the text div has had its left property removed. It is now affected by the left padding of its container:
("Show code snippet" and run it)
#main {
position: absolute;
top: 141px;
left: 50%;
height: 100%;
width: 960px;
padding: 50px;
margin-left: -290px;
text-align: justify;
background-color: yellow;
}
.header {
position: absolute;
height: 150px;
width: 400px;
left: 290px;
background: #F00;
}
.left {
position: absolute;
height: 300px;
width: 233px;
top: 180px;
background: #F00;
}
.text {
position: absolute;
top: 200px;
background: #F00;
}
<div id="main">
<div class="header">
<img src="http://www.placehold.it/200" />
</div>
<div class="left">
<img src="http://www.placehold.it/200" />
</div>
<div class="text">You can't handle the truth, soldier!</div>
</div>
Is position: absolute the best way to layout my elements?
Depends... position: absolute removes elements from the normal flow of the document. That is, each element is essentially invisible to the other. This is particularly problematic if you wish to create a flexible layout, which can re-size in accordance with the users browser height / width.
Can you show me another way to layout HTML elements?
Sure! There are many ways to layout a page without resorting to position: absolute. Here is a basic example using display: flex — a newer way to layout elements. It does not enjoy 100% browser support yet, so this is purely an example of one technique :)
Read more:
about vw and vh units on the MDN
about flexbox over on CSS-Tricks - A Complete Guide to Flexbox
about flexbox browser support
Flex example
Note how the elements resize when the example is made full-screen.
* {
margin: 0;
padding: 0;
}
body {
width: 80vw;
max-width: 800px;
margin: 0 auto;
background: #424242;
}
header {
background: #e91e63;
height: 20vh;
}
.wrap {
display: flex;
}
.left {
background: #fce4ec;
flex: 1;
}
.content {
background: #fafafa;
min-height: 70vh;
flex: 2;
}
footer {
height: 10vh;
background: #c51162;
}
<header>
I am header
</header>
<div class="wrap">
<div class="left">
I am sidebar
</div>
<div class="content">
I am content
</div>
</div>
<footer>
I am footer, hear me roar! RWAR!
</footer>
Define a class .child for your <div>
<div class="child">
and define style accordingly
.child { padding: 10px; }
Use position: relative; on the child divs to make them account for the parent divs padding.
problem is you give left and top to text div that why not accept padding,simply remove left to text div then it will accept the padding...