Whence the horizontal shift in pure-CSS parallax? - css

I'm trying to produce a pure-CSS parallax effect following the approach from this post. It mostly works; however, there are some artifacts when the parallaxed elements are not full-width.
In the snippet below, the hero element (with specified dimensions) is meant to scroll more slowly than the rest of the page. The container's perspective-origin points exactly to the middle of the hero element, so applying transform: translateZ(-1px) scale(2); to the hero should not move it at all. But it does produce a horizontal shift of a few pixels. (Vertical position is fine.)
Why does this happen, and how to fix it?
.container {
height: 500px;
background: #eee;
overflow-y: auto;
overflow-x: hidden;
perspective: 1px;
perspective-origin: 50% 171.5px;
}
.hero {
background: url('http://via.placeholder.com/1256x343');
height: 343px;
margin-left: auto;
margin-right: auto;
transform: translateZ(-1px) scale(2);
max-width: 1256px;
}
.main {
background: rebeccapurple;
height: 2000px;
margin-left: auto;
margin-right: auto;
max-width: 1256px;
}
<div class="container">
<div class="hero"></div>
<div class="main">Scroll me down</div>
</div>

This layout is based on the hero element being perfectly centered on the container.
Then, perspective-origin-x: 50% will work ....
But, as long as you have a scroll bar on the right side, the content-box size is no longer the same in container and hero, and it misses the alignment.
Take a look at this post for more details and a solution that may be could work in your case
html,body{
margin: 0;
height: 100%;
overflow: hidden;
background: #000;
}
#wrapper1{
width: calc(100% + 17px);
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
}
#wrapper2{
width: 100%;
height: 100%;
perspective: 1px;
perspective-origin: calc(100% - 17px) center;
overflow-y: scroll;
}
#wrapper3{
width: 100%;
max-width: 100vw;
transform-style: preserve-3d;
}
.parallax_layer1{
transform-origin: 100% center;
transform: translateZ(-.4px) scale(1.4); /* scale=1-translateZ/perspective */
z-index: -1;
position: relative;
}
section{
background: #111;
height: 50vh;
box-shadow: 0 0 50px rgba(0,0,0,0.7);
width: 100%;
}
img{
width: 100%;
height: 80vh;
margin: -5vh 0;
object-fit: cover;
}

Related

Align everything to the top when used object-fit: contain;

I'm trying make an image occupy entire view area while retaining its aspect ratio.
object-fit: contain; seems to do the trick, except regardless of the window size, the image occupy entire height, pushing everything outside of view area.
.resize img
{
width: 100%;
height: 100%;
object-fit: contain;
object-position: 50% 0;
}
.resize
{
overflow: auto;
resize: both;
border: 2px solid red;
width: 100px; /* inital demo size */
height: 170px; /* inital demo size */
}
<div class="resize">
<span>
<img src="https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj">
</span>
<div>myText</div>
</div>
How can I make the image fit into view area (red box), without leaving empty space below it?
Expected Result
Actual Result
span {
text-align: center;
float: left;
width: 100%;
}
.resize img
{
width: inherit;
height: min-content;
object-fit: scale-down;
object-position: 50%;
margin: 0 auto;
position: relative;
max-width: 350px;
max-height: max-content;
}
.resize
{
overflow: auto;
resize: both;
border: 2px solid red;
min-height:250px;
}
<div class="resize" style="width:100px;">
<span>
<img src="https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj">
</span>
<div>myText</div>
</div>
Use CSS grid to define two rows, one for the image and the other for the text
.resize img {
width: 100%;
height: 100%;
object-fit: contain;
object-position: 50% 0;
}
.resize {
overflow: auto;
display: grid;
grid-template-rows: minmax(0,1fr) auto;
resize: both;
border: 2px solid red;
}
<div class="resize" style="width:100px;height:170px;">
<img src="https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj">
<div>myText</div>
</div>

How can I fix a div relative to a scrollable container?

Please see this minimum example
.container {
position: relative;
width: 200px;
height: 200px;
border: 3px solid gray;
overflow: scroll;
}
.box {
width: 100%;
height: 800px;
background: linear-gradient(0deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%);
}
.loading-cover {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
opacity: 0.5;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="loading-cover">
Loading
</div>
<div class="box"></div>
</div>
I want to fix the white overlay when scrolling.
I've tried inset: 0 or width: 100%;height:100%; on loading-cover, but no luck.
position: sticky; is also unusable in this case because it sticks to the window viewport, not the scrollable container.
Is there any way I can solve this problem?
This might not be the shortest path to a solution, but it does work. It might hold up in cross-browser testing if you don't need to support IE.
This is using a loading class on the container that applies a sticky ::before pseudo-element, with a negative bottom margin to make the content pop up underneath it. A little goofy, but it's a weird situation. I also removed some unnecessary width values and changed overflow to overflow-y, which may or may not be useful in your situation.
With this, you could turn on and off the "Loading" message by adding or removing the class to the container.
.container {
position: relative;
width: 200px;
height: 200px;
border: 3px solid gray;
overflow-y: scroll;
}
.box {
height: 800px;
background: linear-gradient(0deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%);
}
.container.loading::before {
position: sticky;
top: 0;
height: 200px;
margin-bottom: -200px;
background: white;
opacity: 0.5;
display: flex;
align-items: center;
justify-content: center;
content: 'Loading';
}
<div class="container loading">
<div class="box"></div>
</div>

image is been cut at bottom when viewed in a circle using css

I am trying to view a user's profile photo in a circle using this css code:
.circle {
margin: auto;
width: 200px;
height: 200px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
overflow:hidden;
}
.circle img{
width:100%;
}
<div class='circle'>
<img src='https://static.pexels.com/photos/2438/nature-forest-waves-trees.jpg'>
</div>
Problem is, the image is being cut at the bottom:
Yet I expected the image to display in a full circle. Why is this happening and how can I fix it?
As per my comment, you need to use a square image if you want the whole image to be shown, otherwise you need to make the shortest side of the image 100% - in this case the image is landscape so you need to make the height 100% so the extra width will be hidden:
.circle {
margin: auto;
width: 200px;
height: 200px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
overflow: hidden;
}
.circle img {
height: 100%;
}
<div class='circle'>
<img src='https://static.pexels.com/photos/2438/nature-forest-waves-trees.jpg'>
</div>
If you're not interested in IE then object-fit: cover is a great way to make sure that the image will always cover the available space while at the same time keeping its proportions.
.avatar {
display: inline-block;
width: 200px;
height: 200px;
border-radius: 100%;
overflow: hidden;
}
.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="avatar">
<img src="https://static.pexels.com/photos/2438/nature-forest-waves-trees.jpg" />
</div>
<div class="avatar">
<img src="https://images.unsplash.com/photo-1504125130065-19cd3d71c27a?dpr=1&auto=format&fit=crop&w=2134&q=60&cs=tinysrgb" />
</div>
By default img tags take their size from the size of the image file. In this case, the image was larger than 200x200, and so the image extended below the size of your div. By adding height: 100% to the img tag as well, the issue is resolved.
.circle {
margin: auto;
width: 200px;
height: 200px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
overflow: hidden;
}
.circle img {
width: 100%;
height: 100%;
}
<div class='circle'>
<img src='https://static.pexels.com/photos/2438/nature-forest-waves-trees.jpg'>
</div>
Note that the above answer stretches the image to be 200x200. If you don't want this stretching, I would use background-image instead:
.circle {
margin: auto;
width: 200px;
height: 200px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
overflow: hidden;
background-image: url('https://static.pexels.com/photos/2438/nature-forest-waves-trees.jpg');
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
<div class='circle'>
</div>

How can I create div with an opposite-curved bottom

So I found this question: Can I create a div with a Curved bottom?
Thanks to it I managed to make a curved bottom of an image, using code below:
border-radius: 0 0 50% 50% / 15%;
overflow: hidden;
It looks like that:
(practically). Everything would be nice but... I need the curve to be totally opposite way:
How can I do that with clean CSS?
Try this:
div {
height: 250px;
width: 300px;
background: tomato;
position: relative;
margin:0 auto;
}
div:after {
content: "";
height: 50%;
width: 100%;
position: absolute;
background: white;
border-radius: 50%;
bottom: -25%;
transition: all 0.8s;
}
<div></div>
You can't do it with just one div. Border-radius doesn't work that way. However, you can achieve something like that with multiple elements. Overlay a second div on the first with a curved top, masking part of the upper div. If you like, enclose it all in a container with overflow: hidden; to obscure the bottom part of the overlay div.
<div class="container">
<div class="curved">
</div>
<div class="curved-overlay">
</div>
</div>
<style>
.curved-overlay{
border-radius: 50% 50% 0 0 / 15%;
background-color: white;
width: 100px;
height: 100px;
margin-top: -15%;
}
.curved{
background-color: blue;
width: 100px;
height: 100px;
}
.container{
width: 100px;
height: 100px;
overflow: hidden;
}
</style>
Here's the codepen: http://codepen.io/anon/pen/JKjNPa

Stretching DIV to 100% height and width of window but not less than 800x600px

I have a page that needs to stretch and resize with with window and I've managed to do that but I need that the "inner div" (#pgContent) stretch if the window is resized to higher dimensions but that it doesn't shrink more than, let's say for example 800 x 600 px.
As I have it now it stretches well but it also shrinks more than I want!
It's working as I want in width but not in height!?
Here's a visual example:
My CSS:
* {
margin: 0;
padding: 0;
outline: 0;
}
/*| PAGE LAYOUT |*/
html, body {
height: 100%;
width: 100%;
/*text-align: center;*/ /*IE doesn't ~like this*/
cursor: default;
}
#pgWrapper {
z-index: 1;
min-height: 100%;
height: auto !important;
/*min-height: 600px;*/ /* THIS SHOULD WORK BUT IT DOESN'T */
height: 100%;
min-width: 1000px;
width: 100%;
position: absolute;
overflow: hidden;
text-align: center;
background: #000;
}
#pgContent {
position: absolute;
top: 30px;
left: 30px;
right: 30px;
bottom: 50px;
overflow: hidden;
background: #CCC;
}
#footWrapper {
z-index: 2;
height: 50px;
min-width: 940px;
position: absolute;
left: 30px;
right: 30px;
bottom: 0px;
background: #C00;
}
/*| END PAGE LAYOUT |*/
And the HTML:
<body>
<div id="pgWrapper">
<div id="pgContent">
This DIV should stretch with window but never lower than for example 800px x 600px!<br />
If window size is lower then scrollbars should appear.
</div>
</div>
<div id="footWrapper">
<div id="footLft"></div>
<div id="footRgt"></div>
</div>
</body>
If someone could give me a help on this I would appreciate.
Thanks in advance.
The second min-height will overwrite the first one.
Use a height of 100% and min-height of 680px;
#pgWrapper {
z-index: 1;
min-height: 600px;
height: 680px;
min-width: 800px;
width: 100%;
}
I belive height auto is messing with your stretching, commenting it out made your styles behave much better. Of course it might be down to different browsers
#pgWrapper {
z-index: 1;
min-height: 100%;
/*height: auto !important;*/
min-height: 680px;
/* THIS SHOULD WORK BUT IT DOESN'T */
height: 100%;
min-width: 1000px;
width: 100%;
position: absolute;
overflow: hidden;
text-align: center;
background: #000;
}
Working sample:
http://jsfiddle.net/QqMeC/4/
Have you tried using the following in #pgWrapper
overflow: auto;
DEMO: http://jsfiddle.net/jonocairns/LA8hg/

Resources