I am looking for something that would allow me to render an uploaded image with a 3D perspective and a wrap effect like here.
This will be in the form of a cropping preview using a jQuery library such as jCrop
Currently I was able to achieve the 3D perspective using Reflex.js but looking for a more subtle solution with the wrapping effect as well.
Any help will be appreciated :)
Thanks in advance!
Your requirement of IE9 support basically mandates a canvas approach if you want to keep it client-side. You could of course do the rendering server-side and AJAX load the rendered image back in which will work in every browser.
If you decide that you can dump IE versions less than 10 (or at least just show them the normal photo without the transform then you can do the wrap-around effect with a combination of CSS 3D Transforms and CSS2 clip. Something like:
<!DOCTYPE html>
<style>
body { margin: 100px; position: relative; }
.edge { width: 20px; height: 196px; background-size: auto 100%; position: absolute; left: 30px; top: 2px; transform: perspective(600px) rotateY(-45deg); transform-origin: right; }
.panel { position: absolute; left: 31px; top: 0; clip: rect(auto,auto,auto,20px); }
.panel>img { width: 350px; height: 200px; transform: perspective(600px) rotateY(30deg); transform-origin: left; }
</style>
<div class="edge" style="background-image: url(my_image.jpg)"></div>
<div class="panel"><img src="my_image.jpg" /></div>
To break that down, we’ve loaded the user’s image and dropped it into the page, along with a div with the same image set as a background. That div is set to be a thin width and a height that’s almost as tall as the main image. We can use the background-size property to foce the background image to fit the div even if it’s taller.
We then absolutely position those two so that they’re next to each-other. The CSS2 clip property lets us clip off the left 20px of the image so that at this point the div and img look like one image together.
Finally, we set a perspective and transform-origin for each block and rotate them away from each-other around the Y axis. Because of the clipping we have to fudge the .edge block to be slightly smaller than originally (with a 200px tall image I had to drop it to 196px to look good) but that works pretty nicely for me.
Obviously you’d need to fill in the vendor prefixes (-moz-, -ms-, -o-, -webkit) and I’ll leave the shadow as an exercise for the reader (a simple background on the container would probably do).
Related
I am working on a WordPress website and have styled the templates header in CSS. I've given it a different background image and it's working, the only problem I have is on mobile.
On mobile there seems to be a white gap to the right of the image and I was wondering if anyone knows a solution to this?
You header element—
<header id="home" class="header menu-align-center" itemscope="itemscope" itemtype="http://schema.org/WPHeader">
</header>
has a min-height:100px set. Increase that number until the image goes all the way across. Try 112px.
For images I learned for myself that it works best to define the container using an aspect ratio, so that it's forced to take up the space you want it to. And then make the image position: absolute inside the container and force it to fill the parent container using object fit: cover and set both lengths to 100%. The image will then automatically fill 100% height or width whatever of both is required:
<div class="image-container">
<img src="...">
</div>
.image-container {
&:before {
/* create a 1px bar inside the container and stretch it according to padding-top */
content: "";
width: 1px;
margin-left: -1px; /* 1px bar with -1px margin will make sure no space is taken */
float: left;
height: 0;
padding-top: 50px / 150px * 100%; /* height / width ratio. So this would result in 3x as wide than high. 100% always refers to the width of the container which makes this trick work */
}
&:after { /* to clear float */
content: "";
display: table;
clear: both;
}
img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
}
You can then also make the container switch aspect ratio by simply changing the .image-container:before{padding-top:;} in your media queries.
Also note that at best the <div> container would be replaced with a <picture> tag providing some different image sizes. Then you have performance increased and no extra DOM nodes as you need the picture tag anyways.
i'm with a trouble in relation with treatment of image, using intervention image on laravel. The problem is: I have to change aspect ratio of a image, but, in my current way, i'm cropping the image to do it, and important things in this element is being cropped too. So, i was wondering, is it possible add border around on image to create the aspect ratio? If you all would can help me, i'll would be very glad with that.
P.S. Sorry for my english, i'm still learning, haha.
Solution 1
Create a div with the right aspect ratio/dimensions and load the image as a background image with background-size: contain.
div {width: 300px; max-width: 100%;}
div > div {
width: 100%;
padding-bottom: 60%; /* use this for the aspect ratio */
background: black url('http://jekyllcodex.org/uploads/grumpycat2.jpg') center center no-repeat;
background-size: contain;
}
<div><div></div></div>
Working demo: https://codepen.io/anon/pen/ooBaKe
How it works
The padding bottom creates the height for this div (as it has no content). The padding-bottom percentage is the percentage of the width of the parent. Thus, a 2:1 ratio image has a padding-bottom of 50%. A 3:2 ratio image has a padding-bottom of 66.66%.
Why this works
The div inside this div has a width of 100%. This is 300px, as the child div is constrained by its parent. The padding bottom percentage is relative to containing block, and not (as many people think) to the body. Here the containing block is the nearest block-level ancestor, which is the parent element. Note that it would be relative to the body if we used just one div with a fixed width of 300px.
Why this solution is not perfect
This solution is fully responsive, due to the max-width of 100% on the containing div. And if you change your mind and you want images to be cropped instead of contained, you only need to change the background-size to 'cover'. Therefore this looks like a good solution. However, a background images is not a proper image, as it has no 'alt' text and lacks a DOM representation, resulting in all kinds of accessibility problems.
Solution 2
Create a div with the right aspect ratio/dimensions and load the image as img tag with max-width and max-height.
HTML
div {
width: 300px;
max-width: 100%;
position: relative;
}
div > div {
width: 100%;
padding-bottom: 110%; /* use this for the aspect ratio */
background: black;
}
div > div > img {
max-width: 100%;
max-height: 100%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
<div>
<div>
<img src="http://jekyllcodex.org/uploads/grumpycat2.jpg" />
</div>
</div>
Working demo: https://codepen.io/anon/pen/yPgQKJ
About this solution
It works roughly in the same way as the previous one, but this solution is semantically correct. The difference here is that an image element is positioned absolute in the inner div. Its placement is absolute, but relative to its parent at 50% of the left border and 50% of the top. Then the image placement is corrected for its width and height, using the translate function of CSS (otherwise its top left corner would be in the middle of its parent). Because only max-width and max-height are used (and not width and height), the image stays responsive and keeps its aspect ratio.
I need to fit and crop the image into it's wrapper.
<div class="box desktop-3 tablet-3 tablet-ls-3 mobile-3">
<div class="inner-box fullbox">
<a href='#module'>
<div class="image-wrap" >
<img src="../img/placeholder.png" />
</div>
</a>
</div>
</div>
css
.box {
width: 282px;
min-height: 282px;
padding: 10px;
float: left;
}
.inner-box {
width: 100%;
min-height: 282px;
top: 10px;
right: 10px;
bottom: 10px;
left: 10px;
padding: 20px;
}
.fullbox {
padding: 0px;
}
.image-wrap {
...
}
i've tried to put the image as the background like you see below, but that didn't worked for me. I want to have a image section from the image that it fits into the box.
.image-warpper {
background-image: url(...);
background-repeat: no-repeat;
background-size: contain;
}
Do i have to crop the image via php or is it possible to scale or crop it in css?
Thanks
"Do i have to crop the image via php..."
Depending on the Image file-size its strongly recommendable to use PHP for this purpose.
Remember the clients browser will always load the complete image to resize it to the css given values.
So even if you got a style telling the image shall never exceed 100x100px the client's browser will load the full size image.
That could take "very long" if its a giant image (referring to the file size).
There are pretty nice classes/libs you can use with PHP to get a comfortable and easy way to play with images. And your page will be much faster then.
For example i recently found:
http://wideimage.sourceforge.net/
Super sweet thing. Supports chaining and stuff.
You should be able to do this:
.image-wrap img { max-width:100%; height:auto; }
This will constrain, and scale down the image, and set it to be 100% wide, according to however wide the parent element is.
Having in mind that you'll use an img html tag, make the image wrap div in position:relative and overflow:hidden and the image with position:absolute and height:100%, width:auto (or width:100% and height:auto). This way the image will be cropped in the parent container and keep its ratio.
See this demo and resize the frame to see how the image is cropped and resized in various dimensions.
let's say that i have an image
It's size is
height : 150px width : 100px.
I want to get a part of it, let's say the full height, but with width between 30-80px. so it will be
height : 150px width : 100px.
I don't want to scale it. I want to cut a part from it. (thanks for editing, it's called cropping).
How to do it?
There is the (somewhat little-known) clip css property, although it does require that the element being clipped is position: absolute; (which is a shame):
img {
position: absolute;
clip: rect(0 100px 200px 0);
/* clip: shape(top right bottom left); NB 'rect' is the only available option */
}
Reference
jQuery cannot modify image elements like that. Your best option would be to position it within a parent element that has overflow:hidden to give the impression it is cut. Or you can use the clip CSS rule. If you actually wanted to make a new image you could use jQuery to gather coords on the image and patch those back to a server-side script to actually do the heavy-lifting and feed the new image down asynchronously.
Image editing is beyond the scope of JavaScript. You can display only a certain part of an image, but you can't actually change the image file:
<div id="imgwrapper"><img src="blah.jpg" width="100" height="150"></div>
#imgwrapper {
width: 100px;
height: 50px;
overflow: hidden;
position: relative;
}
#imgwrapper img {
position: absolute;
top: -30px;
left: 0;
}
Note that with this solution, the inner image is absolutely positioned but the outer div is relatively positioned, which may suit your page layout better than an absolutely-positioned and clipped image.
I think your best bet is to try and use a html canvas.
http://www.w3schools.com/html5/canvas_drawimage.asp
http://www.w3schools.com/html5/canvas_getimagedata.asp
Both allow for rendering parts of a source image, the getImageData() function also allows to read back the image data and manipulate it (for the whole image or parts of it).
Wondering if anyone has a solution for this.
I would like to present an archive of thumbnail images oldest at the bottom and newest at the top. I would also like the flow itself to be reversed... something like this:
The page should be right aligned, with future images added to the top of the page. I am creating the page dynamically with PHP pulling image filenames from a MySQL DB. The catch here is I would love this layout to be fluid, meaning most PHP tricks for counting images and building the HTML accordingly go out the window.
Is there a way to do this with Javascript or even just CSS?
See: http://jsfiddle.net/thirtydot/pft6p/
This uses float: right to order the divs as required, then transform: scaleY(-1) flips the entire container, and lastly transform: scaleY(-1) again flips each individual image back.
It will work in IE9 and greater and all modern browsers.
CSS:
#container, #container > div {
-webkit-transform: scaleY(-1);
-moz-transform: scaleY(-1);
-ms-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
}
#container {
background: #ccc;
overflow: hidden;
}
#container > div {
float: right;
width: 100px;
height: 150px;
border: 1px solid red;
margin: 15px;
font-size: 48px;
line-height: 150px;
text-align: center;
background: #fff;
}
HTML:
<div id="container">
<div>1</div>
<div>2</div>
<div>3</div>
..
</div>
CSS Flexible Box Module was made for this type of thing. See a quick example I whipped up: http://jsfiddle.net/c6QLC/2/ (look at this in Firefox)
Now the bad news: you can't really rely on it yet. Not only is the spec being rewritten, the current implementation doesn't support box-lines (which I did include in the example), which would allow the items to be in multiple rows as opposed to being overflow.
The new spec is being written into dev versions of some browsers, so it will happen. It's just a matter of time.
In the meantime, perhaps something like Isotope might fit your needs.
Should you want to check out the spec, you can find it here: http://www.w3.org/TR/css3-flexbox/
This can be solved with jquery masonry plugin. It's a bit like isotope but free of charge for private and commercial users.