I have a background image on my website. I want to skew it so that it looks like cover photos on Netflix / Disney Plus (attached below).
Attempt
I tried adding this to my image's CSS, inspired from this question: CSS transform like netflix cover image
transform: rotateY(-30deg) rotateX(40deg) perspective(800px) scale(1.6)
It doesn't produce the desired result, though. Instead it slants incorrectly and doesn't stretch the container entirely.
Code sample
Here is my example: https://jsfiddle.net/gd3wL8nk/11/
Screenshots
Update
I got it to work by adding perspective: 2000px to the containing div, and adding this to the inner div:
transform: rotateY(-20deg) rotateX(20deg) scale(2) translateX(-10%)
My final CSS (with edits for measurement, etc) looked like this:
.container {
height: 90vh;
position: relative;
max-width: 100%;
overflow: hidden;
perspective: 2000px;
height: 900
}
.bg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 110%;
background-image: url('image-here');
background-size: cover;
transform: rotateY(-20deg) rotateX(20deg) scale(2);
position: absolute;
top: -10%;
left: 0;
minWidth: 800;
}
See fiddle: https://jsfiddle.net/fernandorojo/kr567zp8/4/
You might be looking for transform: skew();!
i.e.
transform: skew(20deg) scale(1.6);
It won't work with both X and Y rotation though. A good method to ensure it's fullscreen is to use the image as a background in an oversized container. For any children items (like the form, if you nest it in the parent div) you will need to apply the opposite skew to ensure it appears without a slant.
If you check the asset Netflix uses, it's been skewed in Photoshop already.
Related
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
So after a long time of searching, I finally found out how to crop an image without distorting/squashing an image using overflow: hidden;.
Now my next problem; How would I have the image show a part I want, meaning, when using the overflow:hidden it shows the image from the top of it rather than the middle or bottom. How can I adjust that and show the image from the bottom or middle? To help give a better understanding, please view the images below which I created in photoshop. Image description in order: default image, what css does in default with overflow: hidden, what I want (middle pov), what I want (bottom pov).
Thanks.
Edit: My layout is: parent div with the image div as the child. Parent div's height defined at 600px and width at 100%. And height and width of image div defined as 100%.
Assuming your desired width/height and overflow: hidden is applied to an outer containing div, you can add something like:
.container img {
position: relative;
top: 50%;
transform: translateY(-50%);
}
This would move the displayed area of the image down 50% of the container height (top: 50%), then back up 50% of the image height (transform: translateY(-50%)), which ends up centering it inside the container.
You can adjust these values to achieve different positioning, or add in left: and transform: translateX() to adjust the horizontal axis.
In which way are you using this image?
If you're using this as a background image the solution is much simpler and would simply involve using background positioning. If you're using this as an image pulled in using an img tag you can try the below to manipulate the image.
Be aware that this won't work on every browser.
.new-image-container {
position: relative;
width: 250px;
height: 250px;
overflow: hidden;
}
.new-image-container img {
position: absolute;
left: 50%;
top: 50%;
height: 100%;
width: auto;
-webkit-transform: translate(-50%,-90%);
-ms-transform: translate(-50%,-90%);
transform: translate(-50%,-90%);
}
<div class="new-image-container">
<img src="http://i.stack.imgur.com/j8aQR.jpg"></img>
</div>
Here is my answer/solution for anyone that comes across this post.
#Banner {
width: 100%;
height: 350px
}
#backgroundBanner {
width: 100%;
height: 100%;
overflow: hidden;
}
#backgroundBanner img {
width: 100%;
position: relative;
top: 70%; /*make changes to this and below to adjust the positioning of the image*/
transform: translateY(-70%);
<div id="Banner">
<div id="backgroundBanner">
<img src="https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/55312/versions/4/screenshot.jpg">
</div>
</div>
As the question says, I am trying to center a div on the middle of the screen both horizontally/vertically and resize it at the same time.
I do not have any problems on resizing the content when the screen is smaller even to center the wrapper when it is displayed on big screens, the problems comes when I try to resize the screen and, as the wrapper has a max-height property, it does not never vertically center when resize the screen (because it occupy 300px all the time).
I would like that the div that is centered (wrapper) never will be more than 300px and will be always centered (both vertically/horizontally).
Here is my code:
HTML:
<div id="wrapper">
<div id="content">
</div>
</div>
CSS:
html{
width: 100%;
}
body{
width: 100%;
background-color: red;
margin: 0;
}
#wrapper{
position: absolute;
max-width: 300px;
max-height: 300px;
width: 100%;
height: 100%;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
}
#content{
position: absolute;
width: 100%;
padding-bottom: 100%;
background-color: yellow;
}
JSFiddle.
I tried a lot of configurations and looked a lot of questions here on StackOverflow but any of them worked for me because most of them are only for horizontally/vertically center or resize a div, but not both.
Note: I cannot use flexbox and I would like to maintain as much as possible the actual CSS code, if possible.
How can I avoid to use max-height (that is broken my vertically centering) and get the same behaviour?
EDIT: The div is already centered both vertically/horizontally. What I want is that the square will be always a square and always be centered. I am sorry if I do not put it very clear.
Now the content is being resize as I want (as a square), the problem is only with vertically align at the same time it resizes.
EDIT 2: If you want to see the effect that I refer in the above edit, resize the screen on my example JSFiddle horizontally and you will see the effect.
Thanks in advance!
You can easily do this with CSS3 transform. It depends of the browsers support you want to offer.
I would suggest to place your content absolute at 50% of your wrapper. Then, you can use a negative translate of 50%. top: 50% and left: 50% will place your content top left corner in the middle. Negative translate of 50% (translate(-50%, -50%)) will move your content half of its width to the left and half of its height to the top.
#content{
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
You can see your updated jsfiddle
EDIT
I misunderstood a part of your question the first time. But you can easily merge a part of your solution and mine to get what you want.
You just need to replace height: 100%; with padding-bottom: 100%; of my previous answer above:
#content{
position: absolute;
width: 100%;
padding-bottom: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
See this updated jsfiddle.
Maybe I'm missing something(?), but it looks like you can just add height:100%; to your #content css instead of padding-bottom and it works:
https://jsfiddle.net/puajxgsz/
Also, I played with another way to do it without absolutely positioning anything...because, well, it was sort of interesting:
https://jsfiddle.net/j0ch7oxj/
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.
This is my HTML:
<div id="user-avatar"><img src="/imgs/frame.png" alt=""/></div>
user-avatar class is following:
#user-avatar {
width: 100px;
height: 100px;
margin: auto;
position: relative;
background: url(images/avatars/128.jpg) 50% 50% no-repeat;
}
Frame:
#user-avatar img {
position: absolute;
top: 50%;
left: 50%;
width: 122px;
height: 127px;
margin-top: -62px;
margin-left: -63px;
}
Original user-avatar background image dimensions are 23x25 but I want it to be resized to the 100x100px, and the problem is that whatever I set in the width: xxx attribute it'll not work. The avatar that is behind the frame has everytime his original dimensions.
You can't resize an image set as background of a container. The only way you can resize a image is using a img tag and resizing it with width and height css attributes.
Take a look here may be it helps.
You could use background-size, however only the most current browsers support it: https://developer.mozilla.org/en/CSS/background-size
You can use the CSS3 background-size property, for those browsers that support it, then fall back to a compromise solution for older browsers. The compromise solution could be to set a background color to fill up the space around the background image or to use the background-repeat property to "tile" the image.
For example:
#user_avatar {
...
background: url(images/avatars/128.jpg) blue 50% 50% no-repeat;
background-size: 100px 100px;
}