How to scroll to a div's all edges when zoomed - html

Using CSS alone, I am trying to perform a panning behavior on a div that's positioned absolute inside a parent div.
I ultimately want to change the width and height dynamically (zoom in and out behavior). I want to be able to pan (using scrolling) across the whole child div when the size is bigger than the parent.
The child div has bigger width and I expect to scroll to see all 4 edges of it. But, the scroll only happens to the right side and the bottom side. If I have some content in that div – which would be rendered in the top left corner of the div – I can't scroll to it.
.container {
height: 300px;
background: red;
position: relative;
overflow: scroll;
}
.child {
font: 400 14px/17px 'Roboto';
color: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 200%;
width: 200%;
background: black;
opacity: .5;
}
<div class="container">
<div class="child">
Demo Text To Be Shown
</div>
</div>
In this example, the child div has 200% in width and height. I can't scroll to see the left and top edges.

It's just not possible for an element to scroll further up than the top. Here's what you can do instead: give the container some padding so the child isn't off-screen.
.container {
height: 300px;
padding-top: 150px;
padding-left: 50%;
background: red;
position: relative;
overflow: scroll;
}
.child {
position: absolute;
top: 0;
left: 0;
height: 200%;
width: 200%;
background: black;
opacity: .5;
color: grey;
}
<div class="container">
<div class="child">
Demo Text To Be Shown
</div>
</div>

I'm not sure What you want to achieve. I presume you want to see the text:
I amend a bit your CSS:
.container {
height: 300px;
background: red;
position: relative;
overflow: scroll;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-25%, -25%);
height: 200%;
width: 200%;
background: black;
opacity: .5;
color:red;
}
I change transform from -50 to -25 and add color:red. Text appears in the left top corner.

Related

Transform skew without changing element position

I have created the following markup (an example to demonstrate) with a CSS skew transform:
.wrapper {
height: 100px;
width: 200px;
position: relative;
background-color: orange;
}
.inner {
width: 50%;
height: 100%;
position: absolute;
top: 0;
right: 0;
transform: skew(30deg);
background-color: blue;
opacity: .7;
}
<div class="wrapper">
<div class="inner"></div>
</div>
The problem is that the inner div .inner is being position outside of the container .wrapper even though I set right to 0 because the inner div is skewed 30 degrees. How can I position the inner div with the right most part being at the same position? I could hard code the value of right, but it would appear differently with different screen sizes. If I set the overflow of the outer div to hidden, the right side would still be misaligned. I've seen this post which suggests using transform-origin and -webkit-transform-origin, which I set to right, but none of the solutions worked. What can I do?
You need transform-origin: bottom
.wrapper {
height: 100px;
width: 200px;
position: relative;
background-color: orange;
}
.inner {
width: 50%;
height: 100%;
position: absolute;
top: 0;
right: 0;
transform: skew(30deg);
transform-origin: bottom;
background-color: blue;
opacity: .7;
}
<div class="wrapper">
<div class="inner"></div>
</div>

How to make a <div>'s bottom edge below background image

I have a background image, but I need to place a div that its bottom edge should go below the image. What's the easiest way to do this?
Please see the attached image. The white part is the background image and the blue part is my div over the background.
You can create a relative positioned wrapper and then set absolute positioning with bottom: -10%; or bottom: -20px; for a div over a div with image:
.image-with-block-wrapper {
position: relative;
}
.image {
height: 200px;
border: 1px solid #111;
background: url('https://www.gravatar.com/avatar/f42a832da648291bf80206eda08e3332?s=328&d=identicon&r=PG&f=1');
}
.div-over-bg {
border: 1px solid #111;
position: absolute;
height: 50px;
bottom: -10%;
left: 50%;
transform: translateX(-50%);
background: green;
width: 100px;
margin: 0 auto;
}
<html>
<head></head>
<body>
<div class='image-with-block-wrapper'>
<div class='image'></div>
<div class='div-over-bg'></div>
</div>
</body>
</html>
Edit:
In the case of using percents for bottom it will be related with the wrapper height, but you can use bottom: 0;
and transform: translate(-50%, 15%); in order to set the upper block vertical position as relative to the block itself.
So I've created a container with a background image and placed a div inside.
I've given the .block margin: auto; to center it and added position: relative; so I can move it, because it has position: relative; I can add top: 100px; to move it down from the top by 100px
.container {
background-image: url('https://via.placeholder.com/150');
width: 100%;
background-position: cover;
height: 300px;
position: relative;
}
.container .block {
height: 300px;
background-color: blue;
width: 500px;
position: relative;
margin: auto;
top: 100px;
}
<div class="container">
<div class="block">
</div>
</div>
Extra info by #I_Can_Help
In the case of using percents for bottom it will be related with the wrapper height, but you can use bottom: 0;
and transform: translate(-50%, 15%); in order to set the upper block vertical position as relative to the block itself.

How do I center a div ontop of another div that has inline block

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>

Div with position absolute having innerwidth of div with scrollbar

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

Div wider than container rotation off center

I am trying to create a div that is covers the browser window diagonally. See example here:
This is my CSS:
.shape {
height: 100%;
width: 150%;
transform: rotate(25deg);
}
This is my actual result:
I've tried a bunch of different things using transformOrigin and setting top and left of the div, but nothing seems to work to have this div centered diagonally across the browser.
You need to add these: transform-origin: center;
Also when width is more than 100% you need to move content its centered before rotate. Like Position: absolute; left: -25%;
body {
padding: 0px;
margin: 0px;
}
.frame {
width: 100vw;
height: 100vh;
background: #EFEFEF;
}
.rotated {
position: absolute;
left: -25%;
width: 150%;
height: 100%;
border: 2px solid blue;
transform: rotate(25deg);
transform-origin: center;
}
<div class='frame'>
<div class='rotated'></div>
</div>