I'm trying to create a website with a few images. I wanted those images to move a little (just a little) when you scroll down. Background-attachement: fixed did not work for me as I just want a little movement, so I tried transform: translateZ() using a guide I found online. However, this does not work. The translateZ() does absolutely nothing to the image. Is this becase it is a background image instead of a regular image?
My code:
<div class="skooma__section-1">
<div src="" alt="" class="skooma__image-1 image-media">
<div class="image-1__image image-media"></div>
</div>
</div>
My SCSS:
.skooma__section-1{
width: 90vw;
margin-top: 5rem;
display: flex;;
flex-direction: row;
align-items: center;
justify-content: space-around;
//parallax
overflow-x: hidden;
overflow-y: scroll;
perspective: 3px;
overflow-y: auto;
transform-style: preserve-3d;
}
.skooma__image-1{
height: 40rem;
width: 40rem;
clip-path: polygon(5% 15%, 80% 20%, 95% 85%, 20% 80%);
//parallax
position: relative;
}
.image-1__image{
background-image: url(./media/skooma-1.jpg);
background-size: 40rem 40rem;
height: 40rem;
width: 40rem;
// parallax
transform: translateZ(10px);
z-index: -1;
}
You need to set perspective as well. What perspective does is that it tells where the viewer is relative to the element, if it's not set or is smaller than translateZ the change is not visible.
transform: perspective(100px) translateZ(50px);
The translateZ() repositions an element along the z-axis in 3D space. Only with css this effect will be always static. If you want an effect for the images to move only a little, only when you scroll, you need to do this and manipulate the DOM with javascript. You can do interesting effects on hover(when you put the mouse cursor on a image) to move a little bit for example with css animations. Also it's a good idea to insert a link with the effect you want to achieve if you see somewhere.
Related
Consider the following structure:
<div id="PARENT_DIV">
<div id="LEFT_CHILD_DIV">
</div>
<div id="RIGHT_CHILD_DIV">
</div>
</div>
Requirements for PARENT_DIV:
PARENT_DIV will be placed in front of all other GUI elements via z-index.
PARENT_DIV should expand both horizontally and vertically based on the variable sizes of LEFT_CHILD_DIV and RIGHT_CHILD_DIV, but only to a certain point. E.g., I need to be able to set the equivalent of max-width and max-height on PARENT_DIV. For vertical height, PARENT_DIV should expand up to the height of the taller child div (but still only up to max-height), and the other child should float to the top.
I need to be able to arbitrarily place PARENT_DIV on the screen by various means (e.g., top: Ypx; left: Xpx; or top: Y%; left: X%; or top: 50%; left: 50%; transform: translate(50%, 50%);, etc.).
Requirements for each of **LEFT_CHILD_DIV and RIGHT_CHILD_DIV:**
LEFT_CHILD_DIV and RIGHT_CHILD_DIV should each expand both horizontally and vertically based on their content, but only to a certain point. E.g., I need to be able to set the equivalent of max-width and max-height independently on LEFT_CHILD_DIV and RIGHT_CHILD_DIV.
LEFT_CHILD_DIV and RIGHT_CHILD_DIV should always be side-by-side, regardless of their capped widths.
LEFT_CHILD_DIV and RIGHT_CHILD_DIV should each/independently vertically scroll their content when they can no longer grow taller (capped by either their max-height rules or PARENT_DIV's max-height rule, whichever comes into effect first.
Please see this example Photoshop mock-up for a visual of what I'm trying to accomplish. I have not been able to find a CSS-related tutorial on how to accomplish exactly the above. I've found bits and pieces, but they do not work when combined together. I've tried numerous CSS combinations/variations on rules like display, overflow, box-sizing, position, etc., and am not achieving any success. How can I accomplish the above requirements using CSS?
I can accomplish this with JavaScript, but would like to avoid scripting if possible, and do this in pure-CSS way.
You can use flexbox like this:
#PARENT_DIV {
position:absolute;
top:50px;
left:150px;
border: 1px solid red;
display: inline-flex;
max-height: 200px;
max-width: 300px;
align-items: flex-start;
}
#LEFT_CHILD_DIV {
border: 1px solid green;
max-width: 180px;
max-height: 100px;
overflow: auto;
}
#LEFT_CHILD_DIV>div {
height: 200px;
width:200px;
background:rgba(0,0,0,0.5);
animation:change 2s infinite alternate linear;
}
#RIGHT_CHILD_DIV {
border: 1px solid orange;
max-width: 80px;
max-height: 50px;
overflow: auto;
}
#RIGHT_CHILD_DIV>div {
width: 200px;
height:300px;
background:rgba(0,0,0,0.5);
animation:change 2s 1s infinite alternate linear;
}
#keyframes change{
to{width:5px;height:20px;}
}
<div id="PARENT_DIV">
<div id="LEFT_CHILD_DIV">
<div></div>
</div>
<div id="RIGHT_CHILD_DIV">
<div></div>
</div>
</div>
I am making a One-Page webstie to practise Flexbox etc.
To do that, Im using PSD file and I have some troubles.
I wanna make rectangle with an oblique upper side with opacity on my background, i read about svg and should I do it with that like on this picture:
(brown thing with opacity throughout the website view)
I have again similar problem. I have a pic:
And it should looks like:
Tips will be great
You could do this with a CSS gradient.
Here I have a <div> with two backgrounds:
the image
a CSS linear gradient on top of it.
The sharp edge of the gradient works because there are two gradient steps that coincide. Meaning the gradient colour jumps straight from transparent to 50% blue.
I've used blue so that it shows up well in this example. In your case, just switch it to brown.
div {
width: 1240px;
height: 648px;
background: linear-gradient(175deg, rgba(0,0,200,0) 0%, rgba(0,0,200,0) 70%, rgba(0,0,200,0.5) 70%, rgba(0,0,200,0.5) 100%),
url(https://i.stack.imgur.com/Rq6eR.jpg);
}
<div></div>
Another approach without gradient.
Create a wrapper
It can be the div with background image. Important thing is you need to overflow: hidden and position: relative.
Create a rectangle and rotate it
You can create a :before pseudo element like this:
.wrapper {
position: relative;
width: 100%;
height: 200px;
background: red;
overflow: hidden;
}
.wrapper:before {
content: '';
position: absolute;
display: block;
background: blue;
opacity: .5;
bottom: -100px;
left: -100px;
right: -100px;
height: 150px;
transform: rotate(-5deg);
}
<div class="wrapper"></div>
I'm trying to make an <img> fill its wrapper entirely at all times without stretching or changing the image proportions.
Seeing as object-fit doesn't work for IE/Edge without polyfills, does this solution cover all edge cases?
.image-wrapper {
width: 200px;
height: 200px;
position: relative;
overflow: hidden;
}
.image-wrapper img {
min-height: 100%;
min-width: 100%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
<div class="image-wrapper">
<img src="*image source here*" alt="*image alt here" />
</div>
The only problems I see with this are images with a very oblong length or width might need to be cropped specifically to show the desired content in the photo...or the position values changed...depending on how the shape of the container is in relation to the shape of the image.
background-size:cover would indeed be the correct way to do this.
.imgwrapper{
background: url(images/yourimage.jpg) no-repeat center center;
background-size: cover;
}
Alternately, there are plugins that will allow you to do this with inline images, though I have found them less than perfect when using images that are significatly different in aspect ratio from the view box.
Example: https://www.jqueryscript.net/other/jQuery-Plugin-To-Resize-Center-An-Image-Within-Its-Container-Image-Cover.html
After css transform:rotateY of a div I have space covering the area of the original div (not rotated).
I have read that layout cannot adapt after transform but was wondering about another possible solutions.
I read a couple of entries in stackoverflow but was not able to solve my issue.
(I tried display: block or inline-block or float).
Here is a fiddle what I have achieved: white space after image rotateY
The center slide should stretch to fill the space between right side of previous slide and right side of next slide. And it should be responsive (no fixed width in px).
And here is my code:
#wrapper {
width: 100%;
display: flex;
flex-direction: row;
}
.slide {
height: 200px;
background-image: url(http://placehold.it/600x300);
background-position: center;
background-size: cover;
color: #fff;
font-size: 20px;
font-family: sans-serif;
text-align: center;
}
.prev {
width: 50%;
transform: rotateY(-65deg);
transform-origin: left;
}
.next {
width: 50%;
transform: rotateY(65deg);
transform-origin: right;
}
<div id="wrapper">
<div class="slide prev">previous slide</div>
<div class="slide center">active slide</div>
<div class="slide next">next slide</div>
</div>
If relevant for an answer: Later I would also like to add more divs, have only three visible and animate the carousel with swipe motion.
You've understood the behaviour right.
If you touch transform property, other parts will not adapt. The initial occupied space (prior to applying transform) is quite dedicated and further changes will not affect that space and same goes for neighbouring elements.
To fill the gap, your best bet is to reverse the left and right values for transform-origins and respect the wrapper workspace as a whole like the code in below and continue developing from there. Keeping transform-origins as their original values will force you to manipulate the .center div dimensions.
.prev {
width: 50%;
transform: rotateY(-65deg);
transform-origin: right;
}
.next {
width: 50%;
transform: rotateY(65deg);
transform-origin: left;
}
.center {
width: 100%;
}
It's very hard to describe animations by words, try to provide samples.
If you're trying to squeeze other divs to a smaller fixed width 50%, then change your approach and modify your code accordingly. Avoid transform property, use only width.
.slide {
height: 200px;
width: 25%;
background-image: url(http://placehold.it/600x300);
background-position: center;
background-size: 100% 100%;
background-repeat: no-repeat;
color: #fff;
font-size: 20px;
font-family: sans-serif;
text-align: center;
}
.slide.active {
width: 100%;
}
And if you want the widths property to be more flexible, like
1st div 9%
2nd div 12%
3rd div 20%
4th div 100% # .active slide
3rd div 20%
2nd div 12%
1st div 9%
then you can achieve this by JavaScript. Calculate the non-active slides around the active one, and distribute the width values by their distance from the active one.
Is it possible to create the following shape as a DIV in CSS.
The browser support is not important.
You cannot skew an element like this directly, you'll need to use two elements (or generated content) and hide certain overflow to make the flat bottom edge:
http://jsfiddle.net/6DQUY/1/
#skew {
height: 240px;
overflow: hidden;
}
.skew {
background: #000;
display: inline-block;
height: 300px;
width: 500px;
margin-top: 100px;
transform: skew(-8deg, -8deg);
}
Note: I removed the cross browser definitions for better readability.
UPDATE: This would be a more fluid example which resizes in set dimensions: http://jsfiddle.net/6DQUY/3/. Note the padding-bottom on the wrapper which defines the ratio. You may have to play around with the percentage amounts.
#skew {
padding-bottom: 20%;
overflow: hidden;
position: relative;
}
.skew {
background: #000;
position: absolute;
top: 30%;
right: 8%;
left: 8%;
height: 100%;
transform: skew(-8deg, -8deg);
}
Using SVG:
Below is a sample using SVG polygon which can also be scaled easily. Text (if required) can be absolutely positioned on top of the shape.
.shape-svg {
position: relative;
height: 100px;
width: 300px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
polygon {
fill: black;
}
/* Just for demo*/
.shape-svg{
transition: all 1s;
}
.shape-svg:hover {
height: 200px;
width: 600px;
}
<div class="shape-svg">
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<polygon points='5,35 100,0 95,100 0,100' />
</svg>
</div>
The shape can be created using SVG clip path also instead of polygon.
Using CSS and Single Element:
The same shape can be achieved with CSS using only one element also. The key is to set the transform-origin as the side that is required to be straight.
.shape{
height: 100px;
width: 300px;
margin-top: 50px;
background: black;
transform-origin: 0% bottom;
transform: perspective(300px) rotateY(-15deg) skewX(-10deg);
transition: all 1s;
}
.shape:hover{
width: 350px;
height: 150px;
transform: perspective(450px) rotateY(-15deg) skewX(-10deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape"></div>
The shape achieved using this method can also be scaled. However as the height of the shape increases, the right side becomes taller and pushes the top-right corner even more higher. So, either the rotation angle needs to be decreased (or) the perspective needs to be increased (shape needs to be moved farther away) for the height of the right side to remain small enough and be within the viewing area. Or else, the margin-top should be increased.
Below is an explanation on why this happens:
Consider a rectangle positioned 300px in front of the viewer's eye. It is being rotated towards to the viewer and as the rotation happens, the side which is getting closer to the user will appear taller than the other side.
We have fixed the transform origin's x coordinate as 0% and so the height of the left side of the shape would be constant and that of the right side would keep increasing based on the rotation angle.
Because the transform origin's y coordinate is bottom, the bottom side of the shape would be kept straight and any height increase on the right side of the element would be projected upwards resulting in the shape going outside of the screen.
There is no such problem if only the width increases because the rotation angle is too minimal and so the shape's right side will never get anywhere close enough to the viewer to look very tall.
The shape in question is not an exact duplicate of the one discussed here but you can get some more ideas by looking at it :)
You could look into CSS transformations (transform) I have created a JsFiddle with a quick example.
HTML
<div class="skew"></div>
CSS
/* Skew the container one way */
.skew {
background: #000;
display: inline-block;
height: 50px;
width: 500px;
margin-top: 100px;
-webkit-transform: skewY(-5deg);
-moz-transform: skewY(-5deg);
-ms-transform: skewY(-5deg);
-o-transform: skewY(-5deg);
transform: skewY(-5deg);
}
NOTE:
You may need to include other transformations to get the unbalanced look.
--EDIT--
Here is another solution but using :before and :after CSS. JsFiddle.