Relative position and overflow auto - css

I have a problem with overflow: auto and position relative? Example of my code is:
div {
border: 3px dashed #ccc;
padding: 20px;
}
div::before { content: attr(class); }
.grandparent { overflow: auto; }
.parent { position: relative; }
.child { position: absolute; height: 60px; background: black; color: white; }
<div class="grandparent">
<div class="parent">
<div class="child"></div>
</div>
</div>
I want the div.child go over div.grandparent but because of div.parent and his position: relative that causes overflowing.
Please note that I need to absolutely position elements inside .parent - the position being relative to .parent - (which is why I need position: relative here), and I also need a scrollable .grandparent.
Expected result:

div, div.child::after {
border: 3px dashed #ccc;
padding: 20px;
}
div::before { content: attr(class); }
.grandparent { overflow: auto; }
.parent { position: relative;}
.child::before{ content: " " }
.child {position: relative; overflow: auto; }
.child::after {content: attr(class); position: absolute; height: 60px; background: black; color: white;
}
<div class="grandparent">
<div class="parent">
<div class="child"></div>
</div>
</div>
this is your answer but It does not seem practical
Because in reality it can not be implemented in this way
Please ask your question clearly or with a more practical example

Related

CSS problem with divs and inline components

Imagine a code like this:
.div {
width: 100%;
height: 100px;
background-color: green;
}
.div1 {
width: 100px;
height: 100px;
background-color: red;
}
.div2 {
width: 100px;
height: 100px;
background-color: blue;
}
.main {
background-color: yellow;
}
<div class="main">
<div>
<div class="div"></div>
<div class="div1"></div>
</div>
<div class="div2"></div>
</div>
It will render something like this:
I want that the blue div comes up and stay on the right of the red div. Imagine that I canĀ“t change the divs from where they are, so I need to do it in css. How can I do it?
Without changing the markup, if you set float: left to the red <div> then you could put the blue <div> to its right side
.div {
width: 100%;
height: 100px;
background-color: green;
}
.div1 {
width: 100px;
height: 100px;
background-color: red;
float: left;
}
.div2 {
width: 100px;
height: 100px;
background-color: blue;
display: inline-block;
vertical-align: top;
}
.main {
background-color: yellow;
}
<div class="main">
<div>
<div class="div"></div>
<div class="div1"></div>
</div>
<div class="div2"></div>
</div>
The previous solution which uses float on the red div works well, but here is another possible solution:
Apply position: relative; to the blue div (to be able to move it in relation to its default position) and add top: -100px; left: 100px; to move it up next to the red div:
.div {
width: 100%;
height: 100px;
background-color: green;
}
.div1 {
width: 100px;
height: 100px;
background-color: red;
}
.div2 {
width: 100px;
height: 100px;
background-color: blue;
position: relative;
top: -100px;
left: 100px;
}
.main {
background-color: yellow;
}
<div class="main">
<div>
<div class="div"></div>
<div class="div1"></div>
</div>
<div class="div2"></div>
</div>
This can also be done with the grid CSS. Here I used a named template box and then in the "chatty verbose" CSS I put the positional related for each "block". I added classes to the CSS just for clarity but you could update to your classes.
I added some color and things just for clarity and visual references but kept the "position relate" in separate CSS chunks.
.main {
font-size: 2rem;
display: grid;
grid-template: "box";
background-color: yellow;
}
.main *,
.main::before {
grid-area: box;
}
.green-block {
place-self: start;
}
.red-block {
width: 50%;
place-self: end start;
}
.blue-block {
width: 50%;
place-self: end end;
}
.green-block {
height: 3rem;
background-color: green;
}
.red-block {
height: 3rem;
background-color: red;
}
.blue-block {
background-color: blue;
}
.blue-block,
.green-block,
.red-block {
/* color for clarity and just to super center the text in the blocks */
display: grid;
color: cyan;
font-family: sans-serif;
text-transform: uppercase;
place-items: center;
}
<div class="main">
<div>
<div class="div green-block">green</div>
<div class="div1 red-block">red</div>
</div>
<div class="div2 blue-block">blue</div>
</div>

Top Border Equal To Wrapping Text Width

In the bellow code the blue block has a green overline that should be the same width as the text and not overflow. Similar to the pink blocks notice how the green border is the same width as the text.
I've tried using display: inline as well with no luck. Is there maybe some hack to get this to work properly?
Fiddle: https://jsfiddle.net/xq10dnb9/
CSS:
html {
font-size: 50px;
}
.blue {
background-color: #a9f4f4;
}
.blocks {
background-color: pink;
width: 700px;
display:flex;
justify-content: space-between;
}
.block {
padding: 5px;
white-space: normal;
}
.block span {
position: relative;
display:inline-block;
/* display:inline; */
}
.block span:before {
content: '';
height: 4px;
background-color: green;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
HTML:
<div class="blocks">
<div class="block"><span>1 Test</span></div>
<div class="block blue"><span>Test123 Test</span></div>
<div class="block"><span>Testi</span></div>
<div class="block"><span>T asd</span></div>
<div class="block"><span>Testing 5</span></div>
</div>
Add width: min-content in:
.block span{
position: relative;
display: inline-block;
border: 1px solid black;
width: min-content;
}
.block {
padding: 5px;
white-space: normal;
}
When you are using padding,you might want to specify where you want to add padding to like padding-top, padding-bottom, padding-right or padding-left. If you just type padding it will just add space to all side.
So, change it to
.block {
padding-top: 5px;
white-space: normal;
}
Is should solve the issue.
And you add this to your code
*{
padding: 0;
margin: 0;
}

Item with fixed position not appearing in right place

I'm trying to add page-to-top code to a page. Everything works fine except for the positioning of the "to top" button.
I've shown the problem in this jsfiddle. You can see the To Top in the lower right. I need it to be in the lower right of the middle div.
My code is below. I looked up the fixed position description and it says it aligns to the viewport. Is there a way to override that so it aligns to a specific div?
.layout {
float: left;
width: 150px;
height: 200px;
border: 1px solid red;
}
#toTop {
padding: 5px 3px;
position: fixed;
bottom: 0;
right: 5px;
z-index: 100;
}
<div>
<div class="layout">Left column</div>
<div class="layout">Middle column
<span id="toTop">To Top</span>
</div>
<div class="layout">Right column</div>
</div>
You should add position: relative; to .layout and position: absolute; to #toTop. The absolute positioned element will have its relative parent as base
.layout {float:left; width:150px;height:200px;border:1px solid red;position: relative;}
div > span { position: absolute; right: 0; bottom: 0; }
https://jsfiddle.net/oe9fqv3p/13/
This will do it for you.
I added the relative position and in the div > span positioned it absolute and right 0 and bottom 0
I have changed couple of styles in your CSS code. The example is here
https://jsfiddle.net/2yms90qz/
Though i am not sure if you want something like this. Please let me know.
I have removed float from your divs and added inline-block as display. Also changed some position value to achieve the result.
.layout {display: inline-block; width:150px;height:200px;border:1px solid red;}
.middle {
position: relative
}
#toTop {
/* padding: 5px 3px; */
position: absolute;
bottom: 0;
right: 0;
z-index:100;
}
<div>
<div class="layout">Left column</div>
<div class="layout middle">Middle column
<span id="toTop">To Top</span>
</div>
<div class="layout">Right column</div>
</div>
.layout should be positioned and .top should be absolute.
.layout{
position:relative;
}
.top{
position :absolute
}
please see
https://jsfiddle.net/ainouss/39ezf0yj/1/
If you want to keep that "To Top" button always visible on the bottom of the viewport, then you would have to position it relative to the viewport in a way that it matches the location you want, relative to the parent.
body {
margin: 0;
font-family: monospace;
}
.container {
display: flex;
height: 200vh;
width: 90vw;
border: 3px solid red;
margin: 10px auto;
}
.layout {
border-left: 3px solid red;
width: 33.33333333%;
text-align: center;
padding: 10px;
}
.layout:first-child{
border-left: none;
}
#totop {
font-family: monospace;
border: 3px solid red;
background: white;
padding: 10px;
position: fixed;
bottom: 10px;
z-index: 100;
right: calc(35vw + 10px);
outline: none;
}
#totop:hover {
background: red;
color: white;
}
<div class="container">
<div class="layout">Left column</div>
<div class="layout">Middle column
<button id="totop">TO TOP</button>
</div>
<div class="layout">Right column</div>
</div>
<div class="container">
<div class="layout">Something else here.</div>
<div>
Note, however, that as you pointed out in your comment, this means the "To Top" would still be visible even when you scroll past that first .container element.
To avoid that, if you just want that button to be at the bottom of its column, even if that's outside of the viewport and the user needs to scroll down to get to it, then you should use position: absolute instead and also add position: relative to .layout:
body {
margin: 0;
font-family: monospace;
}
.container {
display: flex;
height: 200vh;
width: 90vw;
border: 3px solid red;
margin: 10px auto;
}
.layout {
position: relative;
border-left: 3px solid red;
width: 33.33333333%;
text-align: center;
padding: 10px;
}
.layout:first-child{
border-left: none;
}
#totop {
font-family: monospace;
border: 3px solid red;
background: white;
padding: 10px;
position: absolute;
bottom: 10px;
right: 10px;
outline: none;
}
#totop:hover {
background: red;
color: white;
}
<div class="container">
<div class="layout">Left column</div>
<div class="layout">Middle column
<button id="totop">TO TOP</button>
</div>
<div class="layout">Right column</div>
</div>
<div class="container">
<div class="layout">Something else here.</div>
<div>
To get the best of both worlds, and make the "To Top" button stay at the bottom of the viewport until the end of the first .container is reached, and remain inside it when the user scrolls past it, you could use position: sticky:
body {
margin: 0;
font-family: monospace;
}
.container {
display: flex;
height: 200vh;
width: 90vw;
border: 3px solid red;
margin: 10px auto;
}
.layout {
position: relative;
border-left: 3px solid red;
width: 33.33333333%;
text-align: center;
padding: 10px;
}
.layout:first-child{
border-left: none;
}
#totop {
position: -webkit-sticky;
position: -ms-sticky;
position: sticky;
font-family: monospace;
border: 3px solid red;
background: white;
padding: 10px;
top: calc(100vh - 49px);
float: right;
outline: none;
}
#totop:hover {
background: red;
color: white;
}
<div class="container">
<div class="layout">Left column</div>
<div class="layout">Middle column
<button id="totop">TO TOP</button>
</div>
<div class="layout">Right column</div>
</div>
<div class="container">
<div class="layout">Something else here.</div>
<div>
The only problem with this approach could be browser support.
In that case, if you really need this feature/behaviour, you could implement your own sticky element using JS and listening for the onscroll and 'onresize' events.
Alternatively, you can use JS to check if position: fixed is supported and apply one solution or another:
const hasSticky = (() => {
const el = document.createElement('div');
el.style.cssText = "position:sticky;position:-webkit-sticky;position:-ms-sticky;";
return el.style.cssText.indexOf('sticky')!==-1;
})();
if (hasSticky) {
document.getElementById('totop').classList.add('sticky');
}
body {
margin: 0;
font-family: monospace;
}
.container {
display: flex;
height: 200vh;
width: 90vw;
border: 3px solid red;
margin: 10px auto;
}
.layout {
position: relative;
border-left: 3px solid red;
width: 33.33333333%;
text-align: center;
padding: 10px;
}
.layout:first-child{
border-left: none;
}
#totop {
font-family: monospace;
border: 3px solid red;
background: white;
padding: 10px;
position: absolute;
bottom: 10px;
right: 10px;
outline: none;
}
#totop.sticky {
position: -webkit-sticky;
position: -ms-sticky;
position: sticky;
bottom: auto;
top: calc(100vh - 49px);
right: auto;
float: right;
}
#totop:hover {
background: red;
color: white;
}
<div class="container">
<div class="layout">Left column</div>
<div class="layout">Middle column
<button id="totop">TO TOP</button>
</div>
<div class="layout">Right column</div>
</div>
<div class="container">
<div class="layout">Something else here.</div>
<div>
I changed the scroll code I was using to look for the last button on the page and to hide the To Top button when it reached it. Here is my updated jsfiddle and code. The numbers are not quite correct but I'm just posting this in case someone else runs across this problem. I'm not sure if it is the best solution but I've tested it here and it seems to work fine. My tnaks to all who replied.
<style>
.container {
display: flex;
height: 150vh;
width: 100vw;
}
.layout {float:left; width:150px;height:250px;border:1px solid red;}
.layout-middle {position:relative;float:left; width:150px;height:250px;border:1px solid red;}
#toTop {
font-family: monospace;
border: 3px solid red;
background: white;
padding: 10px;
position: fixed;
bottom: 60px;
z-index: 100;
right: calc(45.33333333% + 10px);
outline: none;
}
</style>
<div class="container">
<div class="layout">Left column</div>
<div class="layout-middle">Middle column
<span id="toTop">To Top</span>
</div>
<div class="layout">Right column</div>
</div>
<div><button id="button-isvisible">Button</button></div>
<script>
$(document).ready(function($){
var offset = 20;
var duration = 500;
$(window).scroll(function() {
var continue_button_pos = $('#button-isvisible').offset();
var button_top = continue_button_pos.top - 350 ;
if ($(this).scrollTop() > button_top) {
$('#toTop').fadeOut(duration);
} else if ($(this).scrollTop() > offset) {
$('#toTop').fadeIn(duration);
} else {
$('#toTop').fadeOut(duration);
}
});
});
</script>

How to align DIV right or left or center in CSS without absolute positioning?

I would like to position some DIV by it's distance from the right side of the container, or from the left side from the container, or centered; but everything without of excluding it from the flow, like absolute does.
Is it possible?
The only thing I can is centered. I can't believe this is not easily possible!
#outer {
position: relative;
width: 100%;
}
#first {
position: relative;
background-color: red;
width: 100px;
right: 10px;
}
#second {
position: relative;
background-color: green;
width: 100px;
}
#third {
position: relative;
background-color: yellow;
width: 100px;
margin-left: auto;
margin-right: auto;
}
The sample is here: https://jsfiddle.net/dimskraft/vm3Lg835/8/
If I make absolute position, another DIV starts to ignore absoluted one...
UPDATE
Visual explanation of what I want:
UPDATE 2
Incredible!
Isn't this task have simple solution? Without any cheating / hacking??
I just want to set distance from right side. Why can't I do this with ONE property???
This one do what you ask, keeping the flow and your original html structure.
I also added a "centered" div, which you commented might be needed.
(As per request, I added a second group of 3 div's in below sample using margins only, and here is also a fiddle: http://jsfiddle.net/qxvoLr5u/2/)
html, body {
margin: 0;
}
#outer {
width: 100%;
text-align: right;
}
#first {
display: inline-block;
width: 100px;
background-color: red;
text-align: left;
margin-right: 10px;
}
#second {
background-color: green;
width:100px;
text-align: left;
}
#third {
display: inline-block;
background-color: yellow;
width:100px;
text-align: left;
position: relative;
right: 50%;
margin-right: -50px;
}
/* sample 2 */
#outer2 div:before {
content: attr(class);
}
.div1 {
width: 100px;
margin-left: auto;
margin-right: 10px;
background-color: red;
}
.div2 {
width: 100px;
margin-right: auto;
background-color: green;
}
.div3 {
width: 100px;
margin-left: auto;
margin-right: auto;
background-color: yellow;
}
<div id="outer">
<div id="first">
</div>
<div id="second">
</div>
<div id="third">
</div>
</div>
<br />
<hr />
As per request, these 3 divs use margin only<br />
<hr />
<div id="outer2">
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
</div>
I would probably wrap it in another relative div that has text-align:right and then give first display:inline-block:
https://jsfiddle.net/aqvug8uj/2/
I think this is best solution https://jsfiddle.net/vm3Lg835/6/
CSS
#outer {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
#first {
background-color: red;
width:100px;
right:10px;
align-self: flex-end;
margin-right: 10px;
}
#second {
background-color: green;
width:100px;
}
I found your question to be a bit confusing, to be honest. If I have understood you correctly, aligning stuff the way you describe it is simple, to the point of being trivial, with float and clear.
#outer {
width=100%;
}
#first {
background-color: red;
width:100px;
float: right;
margin-right:10px;
}
#second {
background-color: green;
width:100px;
clear: right;
}
#third {
background-color: yellow;
width:100px;
margin-left: auto;
margin-right: auto;
}
Is that what you wanted to achieve? Here's the fiddle.
Use the following code:
HTML:
<div id="outer">
<div id="first"> </div>
<div id="second"> </div>
<div class="clearboth"></div>
</div>
CSS:
#outer {
position: absolute;
}
#first {
background-color: red;
width:100px;
float: left;
}
#second {
background-color: green;
width:100px;
float: right;
}
.clearboth
{
clear: both;
}
UPDATEDAdd margin-left: 100px; according to your need.
It should work for you.
Take a look
#outer {
position: relative;
width=100%;
}
#first {
margin-left:350px;
position: relative;
background-color: red;
width:100px;
right:10px;
float:left;
}
#second {
position: relative;
background-color: green;
width:100px;
float:left;
}
<div id="outer">
<div id="first"> </div>
<div id="second"> </div>
</div>

Trying to get a div positioned over two others either relatively or absolute

HTML:
<div id="outer1">
<div class="bg">
<div class="top"></div>
<div class="base"></div>
</div>
<div class="content"></div>
</div>
<div id="outer2">
<div id="bg">
<div class="top"></div>
<div class="base"></div>
</div>
<div class="content"></div>
</div>
CSS2:
div { width: 100%; }
#outer1, #outer2 {position: relative;}
#outer1 .top { height: 200px; background-color: blue; }
#outer1 .base { height: 200px; background-color: yellow; }
#outer2 .top { height: 200px; background-color: green; }
#outer2 .base { height: 200px; background-color: yellow; }
.content {
width: 160px; margin: 0 auto;
position: relative; bottom: 250px; height: 300px; background-color: white; border: 1px solid black;}
This is the fiddle
The white, black-bordered div (.content) is supposed to sit on the split-coloured background (.bg) (as it is).
Using relative positioning - but the space i've told it to move up by (250px), is still been taken by it's parent (#outer1). (there's a gap between to the two 'outer' divs - they should be touching)
I tried absolute positioning but because the content div is taller than the relative content, the height is not honoured. And becuase it's dynamic content I cannot give it a fixed height (although i did for illustration)
One option is javascript, another is using a background-repeater for the top half.
Can it be achieved with pure CSS2?
Edit: Complete rewrite...
Here is the new fiddle: http://jsfiddle.net/FSXj8/14/
Okay so I took the liberty to start from scratch. Here is the html
<div id="outer1" class="container">
<div class="content">
<div class="innerContent">hello world</div>
</div>
<div class="top"></div>
<div class="base"></div>
</div>
<div id="outer2" class="container">
<div class="content">
<div class="innerContent">hello world</div>
</div>
<div class="top"></div>
<div class="base"></div>
</div>
And here is the CSS
div {
width: 100%;
}
.container {
height: 400px;
display: table;
position: relative;
}
.top, .base {
position: absolute;
left: 0;
height: 50%;
z-index: 0;
}
.top {
top: 0;
}
.base {
bottom: 0;
}
#outer1 .top {
background-color: blue;
}
#outer1 .base {
background-color: yellow;
}
#outer2 .top {
height: 50%;
background-color: green;
}
#outer2 .base {
height: 50%;
background-color: yellow;
}
.innerContent {
min-height: 100px;
border: 1px solid black;
background-color: white;
width: 100px;
}
.content {
display: table-cell;
position: relative;
vertical-align: middle;
z-index: 1;
background-color: transparent;
height: 100%;
}
Not sure if this is what you want, you said something about not using absolute:
.content {
width: 100px; margin 0 auto;
position: absolute; margin-top:-250px; height: 100px; background-color: white; border: 1px solid black;}
http://jsfiddle.net/FSXj8/7/

Resources