Reveal/slide image using clipaths - javascript

I am looking to create an animation that slide an image but not using the traditional slide CSS animations, this not achieve the result I am looking for, so basically the animation contains 2 images, the two images are similar (contains the same content as the same sizes) but colors are inverted.
The code I implemented only slide the image to left or right, I'd like to do the same animations but keeping the image in the same place, like when it slides it reveals the background image content as it progress but colors inverted.
I was thinking to apply the animation to clipath crop rather than actual image, below is a working jsfiddle of the issue I am facing.
$(".btn").click(function() {
$(".reveal").toggleClass("show");
})
html,
body {
background-color: #333;
color: #fff;
width: 100%;
height: 100%;
text-align: center
}
.reveal {
overflow: hidden;
position: relative;
display: inline-block;
}
.reveal:after {
content: " ";
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://i.imgur.com/UBOmQ7T.jpg');
z-index: 2;
transition: all 2s ease;
}
.reveal.show:after {
left: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reveal">
<img src='https://i.imgur.com/R6978y3.jpg' />
</div>
<br />
<button class="btn">Reveal!</button>
https://jsfiddle.net/v7fte3m8

You can do this with multiple background. The trick is to make background-clip of one of them to be content-box then adjust the padding to create the reveal effect:
.box {
width:300px;
height:200px;
box-sizing:border-box;
background:
url('https://i.imgur.com/UBOmQ7T.jpg'),
url('https://i.imgur.com/R6978y3.jpg');
background-clip:
content-box,
padding-box;
background-size:cover;
background-position:center;
transition:1s all;
padding-left:0;
}
.box:hover {
padding-left:300px;
}
<div class="box">
</div>
In case you will always have image with inverted colors you can consider the original image and the invert() filter:
.box {
width:300px;
height:200px;
box-sizing:border-box;
background:
url('https://i.imgur.com/R6978y3.jpg');
background-size:cover;
background-position:center;
}
.box:before {
content:"";
display:block;
height:100%;
background:inherit;
background-clip:content-box;
box-sizing:inherit;
transition:1s all;
padding-left:0;
filter:invert(1);
}
.box:hover:before {
padding-left:300px;
}
<div class="box">
</div>

Related

How to replicate a sliding search bar similar to the one on Petfinder

I try to create something similar to Petfinder search menu.
The problem I'm stuck with is that I can't figure out how to make a slide always appear just before the button(only covering it and not propogate to its borders when I change the size of the screen). When the slide search meets the 'heart' element it should act like it hits a wall and not going through it. So the search menu should appear before the button and replacing the previous content from the left side. I tried many options, included hiding this menu by setting width to 0 vw and heigt to 0 vh and positioning it fixed but it wasn't the case. Look at this picture. When I click the search button the menu appears but how to make it appear right from the button and not from the right edge of the screen as it does now? (see the code below)
The second question is how to incorporate this search to a css flow so it all will act as a flex element as a whole when the size of the screen changes? Because right now this slide not shrink when I change width of the screen.
But my search always gets one width. It gets confusing when the size of the screen gets smaller. It results in elements overlaying one another.
const slide = document.getElementById('slide');
let open = true;
document.getElementById('btn').addEventListener('click', (event) => {
if (open) {
slide.classList.add('show')
}
})
.parent {
background-color: #EEE;
font-family: sans-serif;
font-size: 20px;
padding: 25px;
margin: 0;
overflow: auto;
display: flex;
}
.first,
.second,
.third {
padding: 30px;
}
.first {
background-color: salmon;
flex-basis: 120px;
}
.second {
background-color: yellow;
flex-grow: 1
}
.third {
background-color: #56D7F7;
flex-grow: 1
}
.btn {
background-color: red;
cursor: pointer;
}
.slide {
display: flex;
transform: translateX(100%);
background-color: #FFE689;
top: 0;
position: relative;
transition: transform .3s
cubic-bezier(0, .52, 0, 1);
}
.show {
transform: translateX(80%);
}
<div class='parent'>
<div class='first'>1</div>
<div class='second'>2</div>
<div id='btn' class='btn'>Button</div>
<div class='third'>3</div>
</div>
<div id='slide' class='slide'>
Hello
</div>
The picture above shows how it should look like.
The code here is just for the sake of example, I am doing it on React but the problem is clear.
Well other than inspecting the elements on petfinder's website and deconstructing their styles, this is a rough version that I think performs as you are specifying.
const searchBar = document.querySelector('#search-bar');
const openBtn = document.querySelector('#open-btn');
const closeBtn = document.querySelector('#close-btn');
const brand = document.querySelector('#brand');
openBtn.addEventListener('click', (e) => toggleSlider() );
closeBtn.addEventListener('click', (e) => toggleSlider() );
function toggleSlider(){
searchBar.classList.toggle('open');
brand.classList.toggle('open');
}
.example{
max-width:600px;
margin:0 auto;
display:flex;
align-items:center;
justify-content:space-between;
}
.example .btns{
width:100px;
}
.slide-area{
width:100%;
padding:10px;
background-color: #fff;
display:flex;
align-items:center;
justify-content:space-between;
position: relative;
height:50px;
overflow:hidden;
}
.brand{
z-index:100;
transition:all 1s ease;
}
.brand.open{
color:white;
}
.search-bar{
display: flex;
justify-content:flex-end;
align-items:center;
background-color:purple;
position:absolute;
padding:10px;
right:0;
top:0;
left:0;
bottom:0;
transform: translateX(100%);
transition:all 1s ease;
}
.search-bar form{
display:flex;
justify-content:space-between;
align-content:center;
}
.search-bar input[type="text"]{
margin-left:10px;
}
.search-bar.open{
transform: translateX(0);
}
<header class="example">
<div class="slide-area">
<div id="brand" class="brand">Petfinder</div>
<nav>Menu Stuff</nav>
<button id="open-btn">Search</button>
<div id="search-bar" class="search-bar">
<label>Search:</label>
<form>
<input type="text"/>
<input type="submit" value="search"/>
</form>
<button id="close-btn">X</button>
</div>
</div>
<div class="btns">Heart</div>
<div class="btns">Sign up</div>
<div class="btns">Log in</div>
</header>

Is there a way to mask a sticky element using an absolute element?

I've been trying to create a sticky position image that changes as it scrolls across the border between two sections of my page. So basically, there should be two sticky position images, the top one gets masked by the bottom section and the bottom gets masked by the top section. I am having trouble figuring out a way to mask both images at the same time (you can use the bottom section div to hide the top image, and vice versa, but not both at the same time).
Here's an image to illustrate what I'm trying to do
Here's the code I'm using:
.lblue {
height: 40vh;
width:10vw;
position: -webkit-sticky;
position: sticky;
top:30vh;
left:45vw;
background:lightblue;
}
.lred {
height: 40vh;
width:10vw;
position: -webkit-sticky;
position: sticky;
top:30vh;
left:45vw;
background:lightcoral;
}
.blue {
position: absolute;
top:0;
height:150vh;
width:100vw;
background:blue;
}
.red {
position: absolute;
top:100vh;
height:100vh;
width: 100vw;
background:red;
}
<div class="blue">
<div class="lblue"></div>
</div>
<div class="red">
<div class="lred"></div>
</div>
Thank you!
Here’s a solution. The trick is to use the images as CSS backgrounds, because CSS backgrounds can be easily fixed in the viewport of their parents.
.blue {
position: absolute;
top:0;
height:150vh;
width:100vw;
background: blue fixed linear-gradient(lightblue, lightblue) 45vw 30vh / 10vw 40vh no-repeat;
}
.red {
position: absolute;
top:100vh;
height:100vh;
width: 100vw;
background: red fixed linear-gradient(lightcoral, lightcoral) 45vw 30vh / 10vw 40vh no-repeat;
}
<div class="blue"></div>
<div class="red"></div>
In this solution, you can replace linear-gradient(color, color) by the URL of your image, using url(https://…). I used gradients because, for the browser, gradients are (generated) images. So, this trick actually works with images.
The position: absolute also becomes useless, at least for the demo.
The long background rule may need some explanations. background is a shorthand (= a short way to write several properties in a single line) for:
background-color: red;
background-attachement: fixed;
background-image: linear-gradient(lightcoral, lightcoral);
background-position: 45vw 30vh;
background-size: 10vw 40vh;
background-repeat: no-repeat;
position:fixed can do this if you conside a clip-path trick to hide the overflow so that each element will show only inside its section
.lblue,
.lred {
height: 40vh;
width: 10vw;
position: fixed;
top: 30vh;
left: 45vw;
background: lightblue;
}
.lred {
background: lightcoral;
}
.blue,
.red {
height: 100vh;
background: blue;
clip-path: inset(0 0 0 0); /* this is important */
}
.red {
background: red;
}
body {
margin: 0
}
<div class="blue">
<div class="lblue"></div>
</div>
<div class="red">
<div class="lred"></div>
</div>

Zoom Background Image with CSS or JavaScript

I would like to scale the background image of my div over time, so that it looks like it is zooming in and out (without hovering the mouse over - I'm just looking for the animation to start automatically). But, no matter what I try, the background animation just looks choppy.
If I set the div to scale, then the transition is smooth, but it scales the entire div, not just the background image. For additional information, I am running the most recent version of Chrome, and have tried on both Windows and OS. You can see an example here: https://jsfiddle.net/sdqv19a0/
<div class="site-main-banner">
<div class="caption">
<!-- Bootstrap -->
<div class="container">
<div class="row">
<div class="col-xs-12">
<!-- figure -->
<figure> <img src="images/signature.png" alt="signature"> </figure>
<!-- H1 Heading -->
<h1 class="typewrite" data-period="2000" data-type='[ "Purposeful design", "Data-driven marketing", "Dynamic branding", "I love it all." ]'> <span class="wrap"></span> </h1>
<!-- H2 Heading -->
<h2>graphic designer • web designer • analytical marketer</h2>
<div class="clearfix"> </div>
<!-- Button -->
view my portfolio
</div>
</div>
</div>
</div>
CSS:
.site-main-banner {
float:left;
width:100%;
background:url(https://preview.ibb.co/m8kxST/static_banner_new.jpg) no-repeat center center;
background-attachment:fixed;
background-size:cover;
margin: 0;
padding: 0;
display: block;
clear: both;
position: relative;
text-align:center;
overflow: hidden;
animation: shrink 5s infinite alternate steps(60);
}
#keyframes shrink {
0% {
background-size: 110% 110%;
}
100% {
background-size: 100% 100%;
}
}
.site-main-banner a.theme-btn {
color: #FFFFFF;
border:#FFFFFF solid 1px;
background:none;
box-shadow:none;
}
.site-main-banner a.theme-btn:hover {
color: #bc6ca7;
border:#FFFFFF solid 1px;
background:#FFFFFF;
box-shadow:none;
}
.site-main-banner .caption {
position: relative;
float: left;
top: 50%;
left: 50%;
transform: translate(-50%);
padding:300px 0;
}
.site-main-banner figure {
float:left;
width:100%;
text-align:center;
padding:0 0 15px 0;
}
Suggestions? I am open to a js solution, as well, just am not as comfortable with javascript. Thanks!
Separate your background into its own element behind the main banner so you can apply keyframe animations transforming the scale of the background individually instead.
body, html {
margin: 0;
padding: 0;
}
.site-space-background {
position: fixed; height: 100%; width: 100%;
background: #1A1939 no-repeat center center;
background-image: url(https://preview.ibb.co/m8kxST/static_banner_new.jpg);
background-attachment: fixed;
background-size: cover;
animation: shrink 5s infinite alternate steps(60);
}
#keyframes shrink {
0% {
transform: scale(1.2)
}
100% {
transform: scale(1.0)
}
}
<div class="site-space-background"></div>
<div class="site-main-banner">
<!-- The rest -->
</div>
I would use the css transform property in combination with a pseudo element.
.site-main-banner {
position: relative;
overflow: hidden;
}
.site-main-banner:after {
content: “”;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
background-image: url(...);
// put your animation here
}
I can’t really send you a fully working example as I’m currently on my phone in the subway but I hope you get the idea.
Try using the transform: scale([values]); in your animation.
Using transform element is good for applying scales animation.
Look at this Jsfiddle. I tweaked some of your code (not that much since I only edited your css animation).

SVG Fill Path Animation

I don't have experience with svg and animations, I have the following file jsfiddle which i want to animate the fill path color.
I want to use it as a loader so the new colour should fill the path like Sliding across or something similiar that gives it a look of "loading". You can use any color it's just an example...
Thank you
I know it's not fully the way you want to do it, but view this link:
http://cdn.tinfishcreativedev.eu/eyeLoad/
It has a VERY simple implementation (quite crude at the minute, but just to get you started).
The code in the HTML file is as follows:
<style>
body{
background:#F3F5F6;
text-align: center;
}
.loader{
background: #000;
display: inline-block;
position: relative;
height:63px;
width:100px;
margin-top:300px;
}
.loader img{
display: block;
position: absolute;
top: 0;
left: 0;
z-index:2;
}
.loaderBar{
background: #16C38B;
width: 0;
position: relative;
z-index: 1;
height:100%;
-webkit-animation:grow 2s infinite linear;
}
#-webkit-keyframes grow{
0%{ width:0; }
100%{ width: 100%; }
}
</style>
<div class="loader">
<img src="eye.png" width="100" />
<div class="loaderBar">
</div>
You could even do it with JS instead of keyframes to get it working on the older browsers like IE8 if needed.

jQuery + CSS, remove other images on hover with a fade-like transition

Firstly, What I'm trying to accomplish is when you hover over a thumbnail on the lower left, the other thumbnails will become black. However, what I have now seems wierd as the other images flashes back too quick and has no transition.
Secondly, when you transition between thumbnails, I would like when you hover over a "blackened" image, the image will return with a transition, just like what I have at the bottom of my fiddle example.
I'm sorry for the slight confusion since it's two things combined, but I hope I explained it right.
$('.thumb-box').click(function() {
var theSRC = $(this).find('img').attr('src');
$(this).parents('.image-wrapper').find('.main-image').attr('src', theSRC).fadeIn();
});
//Resize image
$('.thumb-box').hover(function(){
$(this).siblings().find('.child-img').addClass('add-active');
}, function(){
$(this).siblings().find('.child-img').removeClass('add-active');
});
$('.main-image').each(function() {
if ($(this).height() > 550) {
$(this).addClass('higher-than-max');
} else if ($(this).height() <= 550) {
$(this).addClass('not-higher-than-max');
}
});
.parent{
border:1px solid purple;
height:100%;
width:80%;
float:Right;
}
.child{
border:1px solid red;
height:100%;
background:gray;
text-align:center;
}
.child-img{
display:inline-block;
max-width:100%;
margin:0 auto;
}
.image-wrapper{
width:100%;
background:orange;
}
.thumbnails img{
width:auto;
height:100%;
width:100%;
}
.thumbnails{
width:100px;
height:100px;
}
.thumb-box{
height:40%;
width:40%;
display:inline-block;
background:black;
}
.higher-than-max{
max-height:500px;
width:auto;
}
.not-higher-than-max{
max-height:100%;
width:auto;
}
.add-active{
transition:2s;
display:none;
}
.boxes{
height:100px;
width:100px;
background:black;
transition:.5s;
}
.boxes:hover{
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="child">
<div class="image-wrapper">
<img src="http://vignette2.wikia.nocookie.net/pokemon/images/b/b1/025Pikachu_XY_anime_3.png/revision/latest?cb=20140902050035" alt="374x333" class="main-image">
<div class="thumbnails">
<div class="thumb-box">
<img src="http://vignette2.wikia.nocookie.net/pokemon/images/b/b1/025Pikachu_XY_anime_3.png/revision/latest?cb=20140902050035" alt="374x333" class="child-img">
</div>
<div class="thumb-box">
<img src="https://i.kinja-img.com/gawker-media/image/upload/unnbgkdbmsszmazgxkmr.jpg" alt="800x450" class="child-img">
</div>
<div class="thumb-box">
<img src="http://vignette3.wikia.nocookie.net/scratchpad/images/0/02/Pikachu.gif/revision/latest?cb=20150217015901" alt="" class="child-img">
</div>
<div class="thumb-box">
<img src="http://cdn.bulbagarden.net/upload/thumb/0/0d/025Pikachu.png/250px-025Pikachu.png" alt="" class="child-img">
</div>
</div>
</div>
</div>
<div class="accomplish">
Image Hover Transition:
<div class="boxes"></div>
</div>
</div>
Personally, I would do this with pure CSS using pseudo elements to create the black overlays.
.thumb-box {
height: 100px;
position: relative;
width: 100px;
// Black overlay
&:after {
background-color: #000;
content: '';
height: 100%;
left: 0;
opacity: 0;// hide overlay to start
position: absolute;
top: 0;
transition: all 250ms ease-in-out;
width: 100%;
}
}
// Show all black overlays on hover
.thumbs {
&:hover {
.thumb-box:after {
opacity: 1;
}
}
}
// Hide black overlay on individual hovered item
.thumb-box {
&:hover {
&:after {
opacity: 0 !important;
}
}
}
Demo: http://jsbin.com/lanuni/edit?html,css,output
Note: I had to add an additional wrapper around each image since you can’t create pseudo elements on <img> tags (see CSS :after not adding content to certain elements).
I think the issue is your are trying to transition between display: inline-block and display: none
You can't transition display. See this question: Transitions on the display: property
First: it flashes b/c the gap between your thumbnail will force your mouse to hover out, thus create the flickering effect.
to solve this you can use setTimeOut() to delay between hovers.
Second: transition between display:block to display:none don't work well, use opacity instead, and put a black background between your thumbnail

Categories