So I have a CSS issue that I can't seem to get my head around. I have solved this in a number of ways none of which seem to pass WCAG Axe accessibility tests as it mentions overlapping of elements.
I have some text whose position is correct, but I want the background-color of the text to span the whole width of the page without altering the position of the text.
Here's a simple example of the issue I want to solve.
.container {
display: block;
margin: 0 auto;
width: 50%;
background: grey;
height: 100vh;
}
.content {
width: 100%;
background: green;
}
<div class="container">
<p class="content">this is some text I want this text to be positioned here but the green background to span the whole width </p>
</div>
My solution involved an extra absolute div with the background set, but that didn't pass accessibility. Any pointers would be great, I appreciate I'm probably being silly here.
You can add the following settings to .content: position: relative; and left: -50%; to move its left side to the left border, and a left and right padding of 50% to make it wider/full width of its parent and keep the text contents aligned with the .container element:
html,
body {
margin: 0;
}
.container {
display: block;
margin: 0 auto;
width: 50%;
background: grey;
height: 100vh;
}
.content {
width: 100%;
background: green;
position: relative;
left: -50%;
padding-left: 50%;
padding-right: 50%;
}
<div class="container">
<p class="content">this is some text I want this text to be positioned here but the green background to span the whole width </p>
</div>
Note that the added padding would not work if you somewhere have a box-sizing: border-box rule for all your elements. In this case you'd have to add box-sizing: content-box to the .content rule to reset this parameter to its default.
You can achieve this by so many ways, here I have used ::before pseudo element and without setting it's width apply left:-100% and right:-100%. Which is nothing but cover entire visible width.
.container {
display: block;
margin: 0 auto;
width: 50%;
background: grey;
height: 100vh;
}
.content {
position: relative;
width: 100%;
background: green;
}
.content::before {
content: "";
display: inline-block;
height: 100%;
background-color: green;
position: absolute;
top: 0;
right: -100%;
left: -100%;
z-index: -1;
}
<div class="container">
<p class="content">this is some text I want this text to be positioned here but the green background to span the whole width </p>
</div>
an idea using border-image
.container {
display: block;
margin: 0 auto;
width: 50%;
background: grey;
height: 100vh;
}
.content {
margin:0;
border-image: conic-gradient(green 0 0) fill 0//0 100vw;
}
<div class="container">
<p class="content">this is some text I want this text to be positioned here but the green background to span the whole width </p>
</div>
Related
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>
I'm trying to put a green area, a pseudo element, to the right of of a blue element, the pseudo element's parent, such that the green element doesn't increase the width of the red scroll area, the container. My actual use-case is a bit more complex, but it relies on using a pseudo element so this below example sets up the problem well. I've included two blue areas and two green areas simply to show that I want the scroll area to scroll if the blue width is large enough. I just don't want the green area to be part of the calculation:
* {margin:0;padding:0}
div {
display: inline-block;
width: 200px;
height: 200px;
background-color: red;
overflow: auto;
}
span {
display: inline-block;
height: 50px;
position: relative;
background-color: blue;
vertical-align: top;
}
span:before {
content: '';
position: absolute;
left: 100%;
width: 500px;
top: 0;
bottom: 0;
background-color: green;
}
<div>
<span style="width:50px"></span>
<span style="width:250px"></span>
</div>
JS Fiddle
Ideally the green pseudo element would be pulled out of the layout completely and have no width. The problem is for the background-color to work it requires a width. I'm strongly suspecting I can't use background-color for this. If something like outline-right: 500px solid green; existed that would be a solution, but I can't find anything like that. I can't use box-shadow, border-right, or anything else since those all add to the width. Is there any mechanism in CSS that would allow the green area to not be included in the red's scroll width area?
Using an outer container with the inner one set to overflow: hidden; removes the absolutely positioned elements from being included in the width and scroll area calculation.
Using min-width: 100%; ensures that the inner container takes up at least the whole width of the outer container.
* { margin: 0; padding: 0; }
#first {
display: inline-block;
width: 200px;
height: 200px;
background-color: red;
overflow: auto;
}
#second {
display: inline-block;
overflow: hidden;
min-width: 100%;
}
span {
display: inline-block;
height: 50px;
position: relative;
background-color: blue;
vertical-align: top;
}
span:before {
content: '';
position: absolute;
left: 100%;
width: 500px;
top: 0;
bottom: 0;
background-color: green;
}
<div id="first">
<div id="second">
<span style="width:50px;"></span>
<span style="width:250px;"></span>
</div>
</div>
JS Fiddle
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>
I don't know why I'm getting a big space between the top border of TextContainer and the text. (I do have a browser reset)
CSS
#TextContainer {
position: relative;
width: 750px;
height: 400px;
top: 50px;
margin: auto;
border: 2px solid #000;
}
HTML
<div id="Container">
<div id="TextContainer">
<font>(Text)</font>
</div>
</div>
JSFiddle.
In the id container change:
display: block
to
display: inline-block
Here is the change I made:
#Container {
display: inline-block;
position: relative;
z-index: 2;
width: 980px;
height: 900px;
background: #FFF;
top: 5px;
-webkit-transition: top, opacity;
-webkit-transition-duration: 1.5s;
}
works here is the jsfiddle.
http://jsfiddle.net/UbVz7/1/
To clarify the height auto and the block inline.
If you want to set the height to 400px like you have, you will need to set the display: inline-block as I have showed you above.
If you want to make the div auto which will take the size of the content added to the div then it is possible to add height: auto;
#CabeƧalho {
display: block;
position: relative;
z-index: 2;
width: 980px;
height: auto;
background: #FFF;
}
This is because the height being set to 400px is pushing down anything that is in a block element to achieve its 400px.
The inline-block allows the data to overlap which pushes the text back up where you want it.
This is because of your overlapping effect.
With a block element when something does not fit, it is pushed to the next line.
I don't know why but if you change the height to auto, the space goes away. Maybe an alignment issue?
#CabeƧalho {
display: block;
position: relative;
z-index: 2;
width: 980px;
height: auto;
background: #FFF;
}