I'm creating a portfolio site that has a filterable infinite wall gallery underneath a hero image that slides off to the right when you click (and slides back on screen with another click). I'm having trouble though, getting this sliding image to work correctly. The photo gallery will be a headache for another day.
There will be a small right arrow button on the left side. To make this slider more obvious I'd like to animate a slight right-left bounce of the image when you hover over this image, then when you click the arrow (or would probably be better to click anywhere on the pic) it slides off screen to the right, revealing this photo gallery underneath. Then you can slide this image back over the gallery with another arrow button on the right.
I found a solution that's most of the way there, using a label input checkbox with a transition property to get it to show as default and animate off screen with the arrow click, but it slides down, not right. It's a little wonky, and I feel like it could be simplified to some degree.
I also tried changing the input from a checkbox to a button and doing animation keyframes, but the animation only played on refresh, and disappears/reappears instantly with no animation with a button click. I may have just targeted the wrong element though.
This is a very rough ideas as to what I'm going for, just thrown together in XD. Final design will be much more pleasant. I forgot the arrow on the second screen, but there'd be one on the right side of the screen to slide that hero image back over the gallery.
If this could be done in just HTML and CSS that'd be great, but if I need to use js or jQuery to do this properly then that's fine.
This is what I have currently that needs some serious work:
<section>
<div class="pv-wrapper">
<h1>PHOTO + VIDEO</h1>
<div class="btn-container">
<ul>
<li class="automotive">Automotive</li>
<li class="video">Video</li>
<li class="portraits">Portraits</li>
<li class="landscapes">Landscapes</li>
</ul>
</div>
<label class="slider">
<img class="arrow" src="images/right-arrow.png">
<input type="checkbox" name="">
<div class="photo-slider"></div>
</label>
</div>
</section>
.pv-wrapper {
width: 100%;
height: 750px;
position: relative;
border-left: 100px solid orange;
color: rgba(0, 0, 0, 0.5);
font-size: small;
display: inline-block;
}
.pv-wrapper h1 {
font-size: 50px;
color: white;
text-transform: uppercase;
letter-spacing: 3px;
position: absolute;
bottom: 225px;
left: -40px;
margin-left: -30px;
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
-ms-transform: rotate(270deg);
-o-transform: rotate(270deg);
transform: rotate(270deg);
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-o-transform-origin: 0 0;
transform-origin: 0 0;
}
.btn-container ul {
display: inline-block;
padding: 50px 0 0 50px;
font-family: 'Poppins-Light';
font-size: 40px;
line-height: 120%;
}
.btn-container ul li a {
text-decoration: none;
color: black;
}
.btn-container ul li a:hover {
color: #68C8E5;
transition: 0.4s ease;
}
.slider {
margin-left: -20px;
}
.arrow {
width: 20px;
margin-top: 90px;
}
.slider > input {
display: none;
}
.slider > input:not(:checked) ~ .photo-slider {
top: 100px !important;
}
.photo-slider {
position: fixed;
height: 750px;
width: 100%;
top: 100%;
left: 100px;
background: url(../images/rs3-bg.jpg);
background-size: cover;
background-position: 75% 50%;
transition: 0.6s;
}
[1]: https://i.stack.imgur.com/nob93.jpg
Got it to work thanks to #MonsterBasket! Had to make a couple slight changes but this is what worked, including the bounce on hover:
.slider {
margin-left: -20px;
cursor: pointer;
display: inline-block;
}
.photo-slider {
position: fixed;
animation-duration: 1s;
animation-fill-mode: both;
animation-timing-function: ease-in-out;
animation-iteration-count: 1;
animation-delay: 0.5s;
}
.photo-slider:hover {
animation-name: bounce;
}
#keyframes bounce {
0%, 100%, 20%, 50%, 80% {
transform: translateX(0)
}
40% {
transform: translateX(30px)
}
60% {
transform: translateX(15px)
}
}
.slider > input {
display: none;
}
.slider > input:not(:checked) ~ .photo-slider {
top: 100px;
}
.slider > input:checked ~ .photo-slider {
left: calc(100% - 60px);
top: 100px;
}
.arrow {
width: 60px;
margin-top: 345px;
}
.slider > input:not(:checked) ~ .photo-slider .arrow {
transform: rotate(-360deg);
transition: 1s;
}
.slider > input:checked ~ .photo-slider .arrow {
transform: rotate(-180deg);
transition: 1s;
}
.photo-slider {
position: fixed;
height: 750px;
width: 100%;
top: 100%;
left: 100px;
background: url(../images/rs3-bg.jpg);
background-size: cover;
background-position: 75% 50%;
transition: 0.6s;
}
The reason you need a checkbox rather than a button is because pure CSS doesn't record state. So even though you can make a button play an animation on click, you can't set it as "clicked" so that you can then "unclick" it.
In .slider > input:not(:checked) ~ . photo-slider you're saying "when this is not clicked, be 100px from the top. .photo-slider is less specific, so there you're saying "when the above rule doesn't apply, be 100% from the top (off the bottom of the screen". All the other attributes aren't specified in the above rule, so they'll always be applied.
To make it slide off to the right, you just need to play with where and how you list those properties. I don't know exactly how you want to position it within the rest of your page, but I think this should get you most of the way there:
.slider > input:not(:checked) ~ .photo-slider {
left: 0px; /* This will put it hard left when unchecked, you also don't need !important, as this rule is more specific than the one below.*/
}
.photo-slider {
position: fixed;
height: 750px;
width: 100%;
top: 100px;
left: calc(100% - 20px); /* this will leave 20px sticking out from the right side of the screen */
background: url(../images/rs3-bg.jpg);
background-size: cover;
background-position: 75% 50%;
transition: 0.6s;
}
You can probably also change this:
<label class="slider">
<img class="arrow" src="images/right-arrow.png">
<input type="checkbox" name="">
<div class="photo-slider"></div>
</label>
To this:
<label class="slider">
<input type="checkbox" name="">
<div class="photo-slider">
<img class="arrow" src="images/right-arrow.png">
</div>
</label>
Which will keep the arrow on top of your hero image. You'll have to figure out the CSS to position it yourself, but then you could do this to change the direction of the arrow:
.slider > input:not(:checked) ~ .photo-slider .arrow {
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
As for making it bounce on hover, this explains perfectly. Your CSS rule would be .photo-slider:hover.
Related
I have the following code in which the star is automatically "spinning" around the crescent and hovering it makes it "rotate". There is also a button on the left side: when it is hovered, it only changes its background-color and text-color; however, I want the star to start spinning and rotating when the button is hovered (and also want the effects of the button i.e. changing its background color and text color, to maintain simultaneously). I tried using different codes but everything I do results in messing the code up further.
<!DOCTYPE html>
<html>
<head>
<style>
body {
position: relative;
right: -500px;
bottom: -150px;
}
.moon,
.star {
background-position: center; /* Center the image */
background-repeat: no-repeat; /* Do not repeat the image */
background-size: 120%; /* Resize the background image to cover the entire container */
-moz-border-radius: 50%; /* to make circle shape */
-webkit-border-radius: 50%;
border-radius: 50%;
}
.moon {
background-color: transparent;
background-image: url("https://i.stack.imgur.com/0bcIk.png");
position: absolute;
width: 200px;
height: 200px;
margin: 50px;
}
.star {
position: relative;
background-color: transparent;
background-image: url("https://i.stack.imgur.com/gjbgR.png");
width: 100px;
height: 100px;
}
.rotate {
width: 100%;
height: 100%;
-webkit-animation: circle 10s infinite linear;
}
.moon:hover .counterrotate {
width: 50%;
height: 50%;
-webkit-animation: ccircle 10s infinite linear;
}
#-webkit-keyframes circle {
from {
-webkit-transform: rotateZ(0deg);
}
to {
-webkit-transform: rotateZ(360deg);
}
}
#-webkit-keyframes ccircle {
from {
-webkit-transform: rotateZ(360deg);
}
to {
-webkit-transform: rotateZ(0deg);
}
}
.moon:hover .counterrotate {
animation-name: inherit;
animation-duration: 5s;
transition-duration: 0.2s;
}
button {
background-color: white;
color: black;
text-align: center;
padding: 16px 32px;
font-size: 16px;
cursor: pointer;
border: 2px solid green;
display: inline-block;
transition-duration: 0.3s;
position: relative;
left: -350px;
border-radius: 50px;
bottom: -100px;
}
button:hover {
background-color: green;
color: white;
display: inline-block;
border: 1px solid white;
transition: 0.5s;
}
</style>
</head>
<body style="background-color: green">
<div class="moon">
<div class="rotate">
<div class="counterrotate">
<div class="star"></div>
</div>
</div>
</div>
<button>Hover</button>
</body>
</html>
How can I do that?
If I have understood the requirement correctly, you do not need Javascript for this.
However, CSS is not currently able to style a sibling element that is before a hovered element (it can't 'go back up' the DOM). But it can style a sibling element that follows the hovered element.
So the first change is to put the button element before the moon element. Now when the button element is hovered we can select its immediate sibling using the + combinator and from there we can select the rotate and moon elements to give them the animations required for rotating and spinning. (In this case we have left the definition of rotate as it is in the code in the question and introduced the spin animation to keep the star spinning around its center).
Now when the button is hovered the star rotates (moves in a large circle) and spins (rotates about its own center).
This snippet also makes the star spin when it is hovered and doesn't have any movement when there is no hovering. Obviously you can change the styling to have what you want there. Also the counterrotation is removed and the -webkit- prefixes, just to simplify things (and you don't want -webkit- with no vanilla setting set as well as some browsers may not interpret it).
<!DOCTYPE html>
<html>
<head>
<style>
body {
position: relative;
right: -500px;
bottom: -150px;
}
.moon,
.star {
background-position: center;
/* Center the image */
background-repeat: no-repeat;
/* Do not repeat the image */
background-size: 120%;
/* Resize the background image to cover the entire container */
border-radius: 50%;
}
.moon {
background-color: transparent;
background-image: url("https://i.stack.imgur.com/0bcIk.png");
position: absolute;
width: 200px;
height: 200px;
margin: 50px;
}
.star {
position: relative;
background-color: transparent;
background-image: url("https://i.stack.imgur.com/gjbgR.png");
width: 100px;
height: 100px;
transform: rotate(0deg);
}
button:hover+.moon .star,
.star:hover {
animation: spin 5s infinite linear;
}
#keyframes spin {
from {
transform: rotateZ(0deg);
}
to {
transform: rotateZ(360deg);
}
}
button:hover+.moon .rotate {
width: 100%;
height: 100%;
animation: circle 10s infinite linear;
}
#keyframes circle {
from {
transform: rotateZ(0deg);
}
to {
transform: rotateZ(360deg);
}
}
button {
background-color: white;
color: black;
text-align: center;
padding: 16px 32px;
font-size: 16px;
cursor: pointer;
border: 2px solid green;
display: inline-block;
transition-duration: 0.3s;
position: relative;
left: -350px;
border-radius: 50px;
bottom: -100px;
}
button:hover {
background-color: green;
color: white;
display: inline-block;
border: 1px solid white;
transition: 0.5s;
}
</style>
</head>
<body style="background-color: green">
<button>Hover</button>
<div class="moon">
<div class="rotate">
<div class="star"></div>
</div>
</div>
</body>
</html>
I'm currently doing a React app which shows what music I'm listening at that time. Obviously some of song names, album name etc. are longer than others so I want to show overflowing part with animation. I managed to do this and it's kinda okay. Longer text scrolls nicely but my problem is it also animates short texts and that causes some shaking on them during the animation.
Any ideas how to remove that shaking? Also Javascript based solutions are appreciated but this seemed to be shorter solution.
div {
width: 100px;
border: 1px solid black;
}
div p {
overflow: hidden;
white-space: nowrap;
display: inline-block;
position: relative;
min-width: 100%;
animation: 5s linear 0s infinite alternate scrolltext;
}
#keyframes scrolltext {
0%,
25% {
transform: translateX(0%);
left: 0%;
}
75%,
100% {
transform: translateX(-100%);
left: 100%;
}
}
<div>
<p>This is a very long text and rolls nicely</p>
<p>And these</p>
<p>two shaking?!</p>
</div>
use margin-left and margin-right instead of left and right
div {
width: 100px;
border: 1px solid black;
}
div p {
overflow: hidden;
white-space: nowrap;
display: inline-block;
position: relative;
min-width: 100%;
animation: 5s linear 0s infinite alternate scrolltext;
}
#keyframes scrolltext {
0%,
25% {
transform: translateX(0%);
margin-left: 0%;
}
75%,
100% {
transform: translateX(-100%);
margin-left: 100%;
}
}
<div>
<p>This is a very long text and rolls nicely</p>
<p>And these</p>
<p>two shaking?!</p>
</div>
I'm trying to imitate Twitter's notification animation
This is what i came up with so far:
$('button').click(function() {
$('#left').css('width', '400px');
$('#right').css('width', '400px');
});
.wrapper {
position: relative;
min-height: 50px;
}
.left {
position: absolute;
left: 0;
height: 50px;
background: #00AEEF;
}
.right {
position: absolute;
right: 0;
height: 50px;
background: #00AEEF;
}
.banner {
width: 0%;
overflow: hidden;
-webkit-transition: width 1s ease-in-out;
-moz-transition: width 1s ease-in-out;
-o-transition: width 1s ease-in-out;
transition: width 1s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="wrapper">
<div id="left" class="banner left"></div>
<div id="right" class="banner right"></div>
</div>
<div style="margin: 10px;">
<button>start animation</button>
</div>
</div>
But using 2 different divs for left and right animation feels like a hack.
Is there a nicer built-in css animation of that type (to be used on a single div)?
Sliding doors effect (only)
(see below for a full-effect demo)
You could animate the background-position of two linear-gradients placed in a single element (so you wouldn't even need to use two more empty elements for styling purpose) e.g.
div {
background:
linear-gradient(to left, #00AEEF 50%, transparent 0),
linear-gradient(to right, #00AEEF 50%, transparent 0);
background-position: 50vw 0, -50vw 0;
background-repeat: no-repeat;
height: 50px;
transition: background-position 1s;
}
:checked + div {
background-position: 0 0, 0 0;
}
Just set a class via js to trigger the transition (for the sake of simplicity I've activated the effect with a :checked pseudoclass)
Codepen demo
You could also obtain the same effect by the opposite animation: if you place a white gradient over a blue background-color you could animate just the background-size of the gradient like so
div {
background: #00AEEF linear-gradient(to right, #fff, #fff);
background-position: 50% 0;
background-repeat: no-repeat;
background-size: 100% 100%;
height: 50px;
transition: background-size 1s;
}
:checked ~ div { background-size: 0 100%; }
Codepen demo
Comparing the two approaches I personally prefer the last one (less code to type, one single gradient to be animated and it seems smoother. Furthermore, the second demo prevents an annoying rounding issue that sometimes happens in the first one, when repositioning the two gradients occurs, as you can see from the screenshot below)
Full effect (with all the animations/transitions)
To recreate the full effect of this notification, markup and style should of course slightly change: starting from the last demo, I moved the main effect on the <a> element inside the wrapper and I inserted other effects, like the # pulsing with an animation and the final slide down after 5 seconds.
The right arrow is made by the unicode symbol U+3009 and it is placed as the content of the a::after pseudoelement
Note: all properties are unprefixed. Add prefixes where necessary
Codepen Demo (Full effect)
Markup
<div class="notification">
<span>#</span>Miro mentioned you
</div>
CSS (embedding Lato font from google fonts)
* {
font : 1rem "Lato", Arial;
box-sizing : border-box;
}
.notification {
position : relative;
overflow : hidden;
font-weight : 100;
font-size : 1.5rem;
}
.notification a {
display : block;
padding : 1em 3em 1em 2.25em;
width : 100%;
font-size : inherit;
font-weight : inherit;
color : transparent;
background : #00AEEF linear-gradient(to right, #fff, #fff);
text-decoration : none;
background-position : 50% 0;
background-repeat : no-repeat;
background-size : 100% 100%;
}
/* The at-sign: I've also tried to use :first-letter but it
* is unreliable when the first char is not a letter or a digit
*/
.notification a span {
position : absolute;
line-height : 1;
top : 50%;
left : 50%;
color : #fff;
font-weight : bold;
transform : translate(-50%, -50%) scale(0);
transform-origin : 50% 50%;
}
/* The arrow */
.notification a:after {
position : absolute;
content : "\3009";
right : 1em;
top : 50%;
transform : translateY(-50%);
}
/* sliding doors effect, color change and final slide down
* all with proper delays
*/
:checked ~ .notification a {
transition: background-size .2s, color .33s 1s, transform 1s 5s;
transform: translateY(100%);
background-size: 0 100%;
color: #fff;
}
/* pulsing and moving the #-sign */
:checked ~ .notification a span {
animation: pulse-at .66s ease-in-out .33s forwards;
}
#keyframes pulse-at {
0% { transform: scale(0) translate(-50%, -50%); }
20% { transform: scale(1.1) translate(-50%, -50%); }
25% { transform: scale(1) translate(-50%, -50%); }
40% { transform: scale(1) translate(-50%, -50%); left: 50%; }
100% { transform: scale(1) translate(0, -50%); left: 1em; }
}
Final result
I have a problem with css and I have to admit that I am just learning it.
I have a header that stays at the top and a "content" area that should be scrollable.
Here are the two css classes:
body,
div {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
width: 100%;
height: 100%;
}
#header {
overflow: auto;
position: absolute;
width: 100%;
height: 200px;
background-color: #DEE7F2;
border-width: 2px;
border-bottom-width:2px;
border-bottom-color:Black;
border-bottom-style: solid;
}
#main {
overflow: auto;
position: absolute;
top: 200px;
width: 100%;
bottom: 0;
}
<body>
<div id="header">
some stuff here
</div>
<div id="main">
a lot of stuff here
</div>
<body>
This works fine though. Now I added a drop down to select the scale of the "content area" because the content will be quite large.
This is the CSS class that I add to the main div to have the scale of 10%:
.scale10 {
-ms-transform: scale(0.1);
-moz-transform: scale(0.1);
-o-transform: scale(0.1);
-webkit-transform: scale(0.1);
transform: scale(0.1);
-ms-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-o-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
This is how the page look like in 100% scale (without the additional class)
As you can see the page is scaled but is not using the whole width of the screen. Also, the scrollbars do not use the whole width... I want the main page to use the full width thats why I used the "width: 100%" statement in the main class. I tried to remove the statement but then the scrollbars are missing...
What I want is to scale the main-div but leave the width at 100% so that the image uses the whole screen. Also I want scrollbars because the content will still be larger then the screen - even with a scale of 10%.
Can some CSS god help me please?
This should do your effect:
JSFIDDLE
You simply have to wrap your content in another container, and you place this container in your main area. Then you scale not your main area, but just your content.
body,
html {
height: 100%;
}
#main {
width: 100%;
height: 100%;
background-color: black;
overflow: auto;
}
.content {
width: 500px;
height: 400px;
margin: 0 auto;
background-color: white;
transition: all 1s ease;
-webkit-transition: all 1s ease;
}
.content:hover {
width: 120%;
}
<div id="main">
<div class="content"></div>
</div>
Added a hover state just for demonstration.
Saw this cool 3x3 grid on this site and cant seem to re-create the animation it has.
The image folds a bit on hover and folds completely in half on a click.
Reference: http://doyouimpress.com/
I've tried doing something similar in CSS however the :active psuedo selector won't open the page completely unless you hold click. Would I only be able to re-create this animation w jquery?
Here's what I've done so far (webkit only): http://jsfiddle.net/JDH9/4wrnf/8/
HTML
<div id="container">
<div id="test">
<div id="left"></div>
<div id="center"></div>
</div>
CSS
#container {
position: absolute;
top: 50%;
left: 50%;
margin: -200px 0 0 -100px;
-webkit-perspective: 1000;
}
#test {
position: relative;
}
#test div {
width: 200px;
height: 400px;
}
#left {
background: grey;
z-index: 3;
-webkit-transform-origin: 0% 50%;
-webkit-transition-delay: 1s;
}
#center {
background: grey;
z-index: 1;
}
#left {
position: absolute;
top: 0;
left: 0;
-webkit-transition-duration: 2s;
}
#test:hover #left {
-webkit-transform: rotateY(-45deg);
-webkit-transition-delay: 0s;
}
#test:active #left {
-webkit-transform: rotateY(-180deg);
-webkit-transition-delay: 0s;
}