I have a cartoon of an antique "detour" sign that has cataphote reflectors embedded in the letters. I want the reflectors to brighten as the image is hovered. That's easily done, I know, simply by swapping out a version of the image with the reflectors darkened with an image of them brightened on hover (per the markup below). However, doing it this way makes the reflectors appear to blink on or off. I want them to get increasingly bright as the cursor nears the center of the image and, of course, dim as the cursor moves away from it, as would occur in real life. (If your headlights beamed at the reflectors at an oblique angle, the light they reflect back would be dimmer than if your headlights hit them straight on.)
My thought is just to increase the opacity of the brightened version of the image in response to the position of the hovering cursor. So, what I need (I think) is a script that detects the cursor position and increases or decreases the opacity accordingly: opacity: 0; at the edge and opacity: 1; at the center. Probably not too challenging for someone adept in javascript/jquery. I've hunted around for a script that does that or something very close to it but haven't been able to locate one that is close enough for me to modify.
I have an additional issue in that in Firefox, at least, the hover image "flicks" the first time it is invoked. I've tried all of the preloading suggestions I could find here on stackoerflow but none of them work. I found that a sprite solved the flicking problem, but wasn't sure how that would work with the way I want the image to animate. Presuming non-sprite images are the way to go maybe if the script invokes the "bright" version of the image at an initial opacity of 0 as the cursor crosses the threshhold, it will also hide the loading "flick...?" Just a guess. Alternatively, I could redesign the hovered version so that it is just the reflectors if that would solve everything else.
Finally, as you can see, the sign is a button that returns a random page. Assuming what I need to solve this problem is a script, can I run both scripts off of the same id (#detour) or should this script use a class name instead? (I am clearly an example of a little knowledge being a dangerous thing.)
Anyway, here's what I've got.
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#detour {
position: absolute;
background: transparent url(https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3.png) no-repeat center center;
background-size: 100%;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
}
#detour:hover {
background: transparent url(https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3on.png) no-repeat center center;
background-size: 100%;
cursor: pointer;
}
<div class="detour-box">
<button id="detour" class="detour" onclick="randomlink()"></button>
</div>
It's not possible to transition from one image to another on the same element by changing the src or background-image value. But you can do it by having both images, and hiding one by default.
Having one image hidden opens the possibility to fade or crossfade between the images. Lay them on top of each other, with the hidden image on top, and show the hidden image on hover.
The image on top can now fade-in by changing the opacity value. With the transition property you can control the transition.
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#detour {
position: absolute;
display: grid;
grid-template: 1fr / 1fr;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
cursor: pointer;
}
#detour img {
grid-area: 1 / 1 / 2 / 2;
width: 100%;
height: 100%;
}
#detour img:last-child {
opacity: 0;
transition: opacity 250ms ease-in-out;
z-index: 1;
}
#detour:hover img:last-child {
opacity: 1;
}
<div class="detour-box">
<button id="detour" class="detour" onclick="randomlink()">
<img src="https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3.png" alt="Detour sign off"/>
<img src="https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3on.png" alt="Detour sign on"/>
</button>
</div>
If we punch holes in the detour sign we only need one image.
The background image can have a linear gradient put behind it, the color(s) of which are changed as the mouse moves. In this snippet the color is always some gray, going up to white, and is changed depending on the y movement of the mouse. It would be easy to change it to take x into account as well. And there could be a real gradient to the background to give different effects - depends just what effect is wanted.
The JS alters a CSS variable, --col, depending on the distance from the center.
function makeColor(d) {
d = Math.floor(d);
return 'rgb(' + d + ',' + d + ',' + d + ')';//could use rgba to get opacity also
}
const detour = document.getElementById("detour");
const dimCol = 128;//set this to the initial (switched off) r, g and b gray
detour.style.setProperty('--col', makeColor(dimCol));
detour.addEventListener('mouseout', function () {
detour.style.setProperty('--col', makeColor(dimCol));
});
detour.addEventListener('mousemove', function () {
const rect = detour.getBoundingClientRect();// this should be in a window resize function if you have one
const h = rect.height;// ditto
const y = event.clientY - rect.top; //ditto
const distanceY = Math.abs(y - h/2)/h;
const d = 255 * (1 - 2 * distanceY);
detour.style.setProperty('--col', makeColor(dimCol + (d * (255 - dimCol) / 255)));
});
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
div#detour {
position: absolute;
background-color: transparent;
background-image: url(https://ahweb.org.uk/detour-with-holes.png), linear-gradient(to bottom, transparent 0%, transparent 40%, var(--col) 40%, var(--col) 60%, transparent 60%, transparent 100%);
background-repeat: no-repeat;
background-position: center center;
background-size: 100%, 70%;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
margin: 0;
padding: 0;
}
<div class="detour-box">
<div id="detour" class="detour" onclick="randomlink()"></div>
</div>
It is fine to have more than one event listener on an element, so the existing onclick remains.
Related
I have this element with background images:
background-image: url(../img/Icons/about-stars-bg2.svg),
url(../img/about-planet-1.svg),
url(../img/about-planet-2.svg),
url(../img/about-planet-3.svg);
background-position: top 5px center, -115px 200px, left 1055px top 450px,
right -45px top 350px;
background-repeat: no-repeat;
background-size: auto, auto, auto, 100px;
Now I want the planets (every picture except the first one) to move a little bit up, then down. (Float effect).
In jQuery I created a setInterval so I have a loop every 2s. Inside I tried to change the background position. It works if I put
.css('background-position','top 5px center, -155px 200px, left 1255px top 250px, right -15px top 350px');
But this just blinks the planets in 2 sec.
Then I tried:
$('.header').animate({backgroundPosition: '(0px -400px)'}, 1000 );// space here
But nothing happened.
How can I achieve the hover effect up/down ?
Here is the jQuery:
// Move planets up down
$(document).ready(function(){
var i = 0;
setInterval(function(){
//JUST BLINKS, CHANGES LOCATION
//$('.header').css('background-position','top 5px center, -155px 200px, left 1255px top 250px, right -15px top 350px');
//DOESN'T WORK
$('.header').animate({backgroundPosition: '(0px -400px)'}, 1000 );
i++;
},2000);
});
#planets {
height: 90vh;
background-image:
url(//placehold.it/40x40/f0b),
url(//placehold.it/40x40/0bf),
url(//placehold.it/40x40/bf0),
url(//placehold.it/40x40/0fb);
background-position:
50% 15%,
25% 35%,
10% 19%,
80% 60%;
background-repeat: no-repeat;
background-size:
3%,
4%,
5%,
6%;
animation: planets 1s 0.5s ease-in-out alternate infinite;
}
#keyframes planets {
to {
background-position:
50% 45%,
25% 65%,
10% 69%,
80% 20%;
}
}
<div id="planets">
</div>
I am creating an interactive touchscreen display using a program called Intuiface and have created some background tiles/squares that I want to make look 'alive' by transitioning slowly between colours.
I have used a linear-gradient transition in CSS to do it but the problem is that the transition looks choppy. The program is running 12 visible tiles (it is a very large touchscreen).
I have tried using fewer colours and running on more powerful GPUs (I think it is CPU run anyway) but this hasn't helped.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
At the moment the animations are noticeably choppy. I would like the transition to be much smoother. Does anyone know how I can achieve this?
Here is the code snippet.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>
Animating background-* properties can be resource intensive - you can try animating transform for relatively better performance - see demo below using traslate for the animation:
body {
margin: 0;
}
div {
height: 100vh;
overflow: hidden;
}
div:after {
content: '';
display: block;
width: 400vw;
height: 400vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
animation: gradient 15s ease infinite;
}
#keyframes gradient {
50% {
transform: translate(-300vw, -300vh);
}
}
<div></div>
Since your animation lasts 15 seconds, trying to run it at full 60fps would mean calculating 15*60 = 900 frames.
Since the difference between a frame and the next is quite small, you can make the CPU work quite less asking for a stepped animation, for instance with steps(75)
It could be also good to set slight delays between animations, so that they don't execute at the same time
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s infinite steps(75);
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>
I don't know if this exists but I am making for myself a little web builder where I add new HTML element give it attributes I want and their values.
After than I made some CSS changes via Javascript and for border-radius I use this:
function borderRadius(){
var dr = document.getElementById("displayColor");
var rv = document.getElementById("radiusValue");
var tl = document.getElementById("tl").value;
var tr = document.getElementById("tr").value;
var bl = document.getElementById("bl").value;
var br = document.getElementById("br").value;
rv.innerHTML = 'Top-Left: '+tl+'%; Top-Right: '+tr+'%; Bottom-Left: '+bl+'%; Bottom-Right: '+br+'%;';
dr.style.borderTopLeftRadius = tl+'%';
dr.style.borderTopRightRadius = tr+'%';
dr.style.borderBottomLeftRadius = bl+'%';
dr.style.borderBottomRightRadius = br+'%';
}
This code isn't important and it looks like ..
Now my question is can I make trough CSS something like
without make additional elements around?
UPDATE:
As GabyakaG.Petrioli commented, this maybe a solution and with it I am half way there:
.round {
background:
radial-gradient(circle at 0 50%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 100% 50%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 100%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 0, rgba(204,0,0,0) 40%, #c00 10%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 100%;
background-repeat: no-repeat;
padding: 10%;
padding-left: 22%;
padding-right: 22%;
}
<div class="round">By using radial gradients, you can simulate rounded corners with a negative radius. Just in this case, don't put the color stops at the exact same position, since the result will be too aliased in most browsers (and kinda still is in Webkit).</div>
Also here I found the answer and solution but still I have some margins or something:
*{margin: 0; outline:0; border: 0;}
.round {
background:
radial-gradient(circle at 0 100%, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 100% 100%, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 100% 0, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 0 0, rgba(204,0,0,0) 70%, #c00 71%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 50%;
background-repeat: no-repeat;
width: 300px;
height: 300px;
padding: 10%;
transform: rotate(45deg);
}
p{
transform: rotate(-45deg);
width: 100px;
margin: 100px;
}
<div class="round"><p>
By using radial gradients, you can simulate rounded corners with a negative radius. Just in this case,</p></div>
No, there are no inset or inverse border-radius in CSS as of now. But there are very many ways to create this shape. I've answered your radial-gradient question in the other thread but think this is a good enough shapes question to stand on its own and hence giving a detailed answer here with all the different possible methods to create this shape.
Using Radial Gradient:
Just adding here for the benefit of others. It's a repeat but makes the answer complete. We can use four ellipses (or circles) created using radial-gradient background images and place them at their appropriate position to create this effect. The output shape is responsive but it cannot be used when the shape should have :hover effects restricted to the shape boundaries or have anything other than a solid color as the fill/background. It also needs a square shaped container (not a rectangle).
div {
width: 300px;
height: 300px;
}
.radial-grad {
background: radial-gradient(circle at 0 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 0, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 0 0, rgba(204, 0, 0, 0) 70%, #c00 71%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 50%;
background-repeat: no-repeat;
transform: rotate(45deg);
backface-visibility: hidden;
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
width: 350px;
height: 350px;
}
<div class='radial-grad'></div>
Using SVG:
SVG is the recommended tool for creating such complex shapes. We can easily create the required shape using path element and its various commands. SVG is scalable (responsive), is very easy to create and maintain, allows greater control over the shape like its slope etc. It can support gradient or image backgrounds too. Unlike radial-gradient, this works well with rectangular containers too.
By modifying the control point of the quadratic curve (first coordinate provided after the Q command), we can control the slope/curve of the cut-off area. The d attribute of the path element can be set or modified via JS just like we do for any other HTML attributes.
But we have to remember that SVG is a graphic (image). We can't control a HTML element that you're adding to the page through pure SVG alone. That would need clip-paths or something like that.
svg {
height: 300px;
width: 300px;
}
/* just for demo */
svg {
transition: all 1s;
}
svg:hover {
height: 200px;
width: 250px;
}
<svg viewBox='0 0 200 200'>
<defs>
<pattern id='bg' width='200' height='200' patternUnits='userSpaceOnUse'>
<image xlink:href='https://placeimg.com/200/200/nature' height='200' width='200' />
</pattern>
</defs>
<path d='M0,0 Q100,60 200,0 Q140,100 200,200 Q100,140 0,200 Q60,100 0,0z' fill='url(#bg)'/>
</svg>
Using Clip-path:
This is similar to the pure SVG version but unlike that one where the shape is created and then placed behind or inside the container, here we cut the container element itself into the required shape.
Pure CSS method (without SVG) is available but it doesn't support complex paths yet. It supports only basic shapes and so we have to use clip-path along with a SVG definition. Moreover, Firefox supports it only when used with SVG (like url(#id)). IE still doesn't support clip-path and that's one reason why this is not yet good for production implementations.
This is good when the shape has background as an image or a gradient instead of a solid color and it can also work well when :hover effects are needed because we are cutting out the required paths.
This is more like an inset border-radius because the element doesn't exist outside the clipped area.
div {
height: 300px;
width: 300px;
background-image: url(https://placeimg.com/200/200/nature);
}
.clip-path {
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
height: 350px;
width: 325px;
}
<svg width='0' height='0'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 Q0.5,0.3 1,0 Q0.7,0.5 1,1 Q0.5,0.7 0,1 Q0.3,0.5 0,0z' />
</clipPath>
</defs>
</svg>
<div class='clip-path'></div>
Using Masks:
This feature is currently supported only by WebKit powered browsers and hence isn't recommended now but it is a very good option for the future. This approach is especially useful when the shape's background would be an image or a gradient and not just a solid color.
The working of masks is very similar to the radial-gradient approach but the difference lies in the fact that unlike radial-gradient which fills the remaining space with solid color, this would just mask out the unwanted portions and not add any fill of its own. So, the background image that is assigned to the element originally will be preserved.
This method is not good if we want to have :hover effects that is restricted to the boundaries of the shape as it doesn't cut out the unwanted portions, it just masks them out or make it transparent.
Similar to the radial-gradient approach, this also needs a square shaped container to work but it is otherwise responsive.
div {
height: 300px;
width: 300px;
background-image: url(https://placeimg.com/200/200/nature);
}
.mask {
-webkit-mask-image: radial-gradient(circle at 0 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 0, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 0 0, rgba(204, 0, 0, 0) 70%, #c00 71%);
-webkit-mask-position: bottom left, bottom right, top right, top left;
-webkit-mask-size: 50% 50%;
-webkit-mask-repeat: no-repeat;
transform: rotate(45deg);
backface-visibility: hidden;
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
height: 350px;
width: 350px;
}
<div class='mask'></div>
Using Pseudo element and Box shadows:
I don't recommend this approach as it has a lot of drawbacks but is still an option. If we just need to create the shape, don't require :hover effects, don't require the cut off areas to be transparent (that's the cut-off areas can be a solid color, like white in this snippet) then we can try this approach.
It involves placing 2 elliptical pseudo-elements on the top, left side and then getting their shadows to do the work on their opposite sides.
div {
position: relative;
height: 300px;
width: 300px;
background: #c00;
}
div:before {
position: absolute;
content: '';
height: 50%;
width: 110%;
top: -35%;
left: -5%;
background: white;
border-radius: 50%;
box-shadow: 0px 360px 0px 0px white;
}
div:after {
position: absolute;
content: '';
width: 50%;
height: 110%;
left: -35%;
top: -5%;
background: white;
border-radius: 50%;
box-shadow: 360px 0px 0px 0px white;
}
<div></div>
I have an image in <img> tag. My aim is to create a reflection of that image using only CSS.
It also has to be compatible with all browsers. I tried various ways to do it one of them is in this JS Fiddle
What I want:
The Fade to Zero opacity from top to bottom on the reflection. Right now it works only in webkit browsers using combination of -webkit-box-reflect and -webkit-gradient.
I want it to work on Mozilla too.
What I have right now:
As it can be seen in the JSfiddle I got it working in the webkit browsers using:
-webkit-box-reflect: below 0px
-webkit-gradient(linear, left top, left bottombottom, from(transparent), color-stop(70%, transparent) , to(rgba(250, 250, 250, 0.1)));
I tried the following for Mozilla:
#moz-reflect:after {
content: "";
display: block;
background: -moz-element(#moz-reflect) no-repeat;
width: auto;
height: 200px;
margin-bottom: 100px;
-moz-transform: scaleY(-1);
}
where #moz-reflect is the container div for the <img>.
I'd appreciate answers which can solve the problem with CSS only. There are a lot of images (Icons) to which this effect has to be applied.
If there is no way it can be made to work in Mozilla using just CSS then I wouldn't mind going down the JavaScript road.
Update
It has to work on custom background which may be an image or black or any other color.
I've changed your code totally, I am using CSS3 gradients with transform property, this is Pure CSS with maximum compatibility.
Here, the key thing I am using is rgba() along with the transform property applied to second img which am targeting using nth-of-type pseudo.
Also, make sure that you have called position: relative; on the parent element because I am using :after pseudo for the gradient overlay from the bottom, so am using position: absolute; for that with the bottom set to 0
Demo (Had made a bit mistake here by using rotate() as it won't give reflection effect, will just rotate the image infact, please refer to my second demonstration)
Demo 2 (Using scale for mirroring images, can use rotateY as well, as pointed out in the comments..)
#moz-reflect:after {
content:"";
width: 100%;
height: 200px;
position: absolute;
bottom: 0;
left: 0;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.67) 49%, rgba(255, 255, 255, 1) 100%);
/*I've removed proprietary gradient codes from here, you can get it in the demo*/
}
#moz-reflect img:nth-of-type(2) {
-webkit-transform: scaleY(-1);
-moz-transform: scaleY(-1);
-ms-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
}
#moz-reflect {
position: relative;
}
Demo 3 (Only difference is, that am using height: 50%; for the :after pseudo so we don't have to hard code it)
Only code to modify in the above block of code is the height property which am setting to 50%
#moz-reflect:after {
content:"";
width: 100%;
height: 50%; /* Changed the unit over here */
position: absolute;
bottom: 0;
left: 0;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.67) 49%, rgba(255, 255, 255, 1) 100%);
}
Note: Inorder to create the gradients best suited, say black opaque gradients will be required for websites with black background, than you can make your own using Color Zilla.
Image reflection, using black as the body background. Only changes in the above snippet of code is that am applying background: #000; to body and I've tweaked the gradient accordingly.
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.67) 49%, rgba(0, 0, 0, 1) 100%);
Demo (For websites using darker backgrounds, black in this case)
Note: Didn't added proprietary properties for gradient in the black demo
You can also use a single image element along with ::before and ::after, however it's not very useful (yet), since you have to hard-code a background-image:url() for the ::before pseudo-element. I'm posting this answer because someone else may want to do it this way, and hopefully one day we'll be able to use background-image: attr(src, url); syntax. (1) As of June 2014, no browsers support this.
A fiddle: http://jsfiddle.net/DeedH/5/
I'm assuming you have a black background.
Structure:
img - main image (actually displayed as a background-image),
::before containing the reflection. Must be display:inline-block in order to use the transform:scaleY to flip the image.
::after containing a gradient mask.
The html: (note that currently the src is not used).
<img class="reflect" src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSYXWxD2yC7m2m1ZylyVq_r6yWE4ewJv64cmt3CpgbGdqZq3wEx" />
The CSS:
.reflect {
position:relative;
display:block;
height:300px;
width:300px;
background-image:url('https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSYXWxD2yC7m2m1ZylyVq_r6yWE4ewJv64cmt3CpgbGdqZq3wEx');
background-repeat:no-repeat;
background-size:contain;
content:'';
}
.reflect::before {
position:relative;
top:20%;
height:100%;
width:100%;
display: inline-block;
-moz-transform: scaleY(-.7);
-o-transform: scaleY(-.7);
-webkit-transform: scaleY(-.7);
transform:scaleY(-.7);
opacity:0.2;
background-image:url('https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSYXWxD2yC7m2m1ZylyVq_r6yWE4ewJv64cmt3CpgbGdqZq3wEx');
background-repeat:no-repeat;
background-size:contain;
content:'';
}
.reflect::after {
position:relative;
top:-40%;
height:70%;
width:100%;
background-image:-webkit-radial-gradient(top center, 50% 75%, rgba(0,0,0,0), rgba(0,0,0,1));
background-image:-moz-radial-gradient(top center, 50% 75%, rgba(0,0,0,0), rgba(0,0,0,1));
background-image:-o-radial-gradient(top center, 50% 75%, rgba(0,0,0,0), rgba(0,0,0,1));
background-image:radial-gradient(top center, 50% 75%, rgba(0,0,0,0), rgba(0,0,0,1));
background-repeat:no-repeat;
background-size:contain;
content:'';
}
Note that you must use content:''; on the img itself, otherwise the pseudo-elements won't display.
Also be aware that this is not really applicable to a class of images because you have to hard-code the image url. But this could be useful if you used it by id and used js to write the rules to a document level stylesheet. Otherwise, this is only helpful for single images.
(1). Using HTML data-attribute to set CSS background-image url
I'm trying to create a CSS transform on a div that makes it look like the cover of a book opening.
This means the left side is bound, and the right side flys towards the user getting larger.
Can anyone offer some direction? If it works in webkit that is all I need!
EDIT: I'm looking for the effect you would find with a hardcover book. I don't want the pages to bend or fold, just the right side comes out at the user.
I've done this, it's pretty close but I can't get the left side to lock in place.
#-webkit-keyframes BookCover
0%
-webkit-transform perspective(400px) rotateY(0deg)
opacity 1
100%
-webkit-transform perspective(400px) rotateY(-90deg)
opacity 0
got it, you need to change the orgin -webkit-transform-origin top left
CSS Play has a demo for a css only flipbook : http://www.cssplay.co.uk/menu/peter-rabbit.html
Take a look at the source for some inspiration.
To create a more true 3D effect, the matrix3D tranformations are the coolest thing since sliced bread, but currently only supported in Chrome.
EDIT:
Created a a little test fiddle for 3D transforms, try tweaking it to get the result you want :
http://jsfiddle.net/XnA2f/
here's a fiddle I just made for a peel effect:
http://jsfiddle.net/pixelass/TW43V/17/
for a hardcover feel you would have to play around with rotate3d, which only works on the iOS and Safari mac OS X as far as I know.
peel effect with rotate3d (Safari OS X)
http://jsfiddle.net/pixelass/TW43V/18/
UPDATE:
basic hardcover flip
Hardcover CSS flip
.book {
height: 300px;
width: 600px;
background: red;
position: relative;
perspective: 2000;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.4) 0, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.2) 45%, rgba(0, 0, 0, 0.2) 55%, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 0.2) 100%);
}
.page {
height: 270px;
width: 285px;
position: absolute;
top: 15px;
right: 15px;
transition: transform 300ms linear;
transform-origin: 0 0;
background: white;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.4) 0, #fff 10%, #fff 50%, rgba(0, 0, 0, 0.2) 100%);
z-index: 1;
&:hover {
z-index: 2;
}
&.flipped {
transform: rotate3d(0, 1, 0, -180deg);
}
}
Here's a working example http://www.romancortes.com/ficheros/page-flip.html
I've never done it before but I would imagine that CSS could only go so far. I think Jquery is maybe a bit of a better option.
But if I was to do it in CSS i'd have a container div that then uses the CSS pseudo selector :before or :after. Which simply attaches an element to another using only CSS. I'd style them however. Then I would expand using -webkit-transform or whatever, when the user hovers etc.
Heres a guy thats pretty good with CSS and design in general, he has a free example
http://www.sohtanaka.com/web-design/simple-page-peel-effect-with-jquery-css/
Heres a link to the pseudo selector
http://w3schools.com/cssref/sel_before.asp
#-webkit-keyframes BookCover
0%
-webkit-transform perspective(400px) rotateY(0deg)
-webkit-transform-origin top left
100%
-webkit-transform perspective(400px) rotateY(-90deg)
-webkit-transform-origin top left
(written in stylus)
HTML
<div>book cover</div>
CSS
div {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: blue;
}
div:hover {
-webkit-transition: -webkit-transform 3s ease;
-webkit-transform: rotateY(-90deg) skewY(-45deg);
-webkit-transform-origin: 0 0 0;
}
See fiddle for a live demo.