:after element with rotate moving on resize - html

I have a :before and an :after element (for shadow purposes) with a transform: rotate applied to it. The :before stays in place when the viewport is resized, however the :after moves slightly up and down. If the rotate is removed, it stays in place on resize. How can I make it stay in place on resize with the roate?
I have put a z-index: 1 on the :before and :after for visibility of the issue
It's the shadow #3
http://codepen.io/mildrenben/details/jEYpyP/
HTML:
<h2>Shadow #3</h2>
<div class="row shadow-3">
<div class="shadow-box">
<img>
</div>
<div class="shadow-box">
<img>
</div>
<div class="shadow-box">
<img>
</div>
<div class="shadow-box">
<img>
</div>
</div>
CSS:
html, body {
width: 100%;
height: 100%;
}
.row {
height: 160px;
width: 80%;
margin: 0 auto 60px;
display: block;
img:nth-of-type(1) {
content: url(http://marshall.org/wp-content/themes/marshall/img/featured-space-policy.jpg);
}
img:nth-of-type(2) {
content: url(http://i.dailymail.co.uk/i/pix/2014/09/04/1409790551890_wps_28_Astronaut_Reid_Wiseman_po.jpg);
}
img:nth-of-type(3) {
content: url(http://cdn2.collective-evolution.com/assets/uploads/2014/08/life_in_space-728x400.jpg);
}
img:nth-of-type(4) {
content: url(http://s.ngm.com/2007/10/space-travel/img/space_feature.jpg);
}
}
img {
width: 23%;
margin: 0 1% 0 0;
height: 100%;
transition: all 0.2s ease-in-out;
cursor: pointer;
}
.shadow-box {
width: 23%;
margin: 0 1% 0 0;
height: 100%;
transition: all 0.2s ease-in-out;
cursor: pointer;
display: inline-block;
img {
width: 100%;
height: 100%;
&:hover {
transform: translateY(-4px);
}
}
}
.shadow-box:before, .shadow-box:after {
content: '';
z-index: 1;
position: absolute;
width: 8%;
height: 110px;
background: red;
transform: skew(-10deg) rotate(-6deg) translate(calc(3% + 10px), 31px);
transition: all 0.2s ease-in-out;
}
.shadow-box:after {
transform: skew(10deg) rotate(6deg) translate(126%, -146px);
}
.shadow-box:hover:before, .shadow-box:hover:after {
box-shadow: 0 20px 20px lighten($black, 40%);
}

I don't think using translates is the way to go here, I'd set the container to position: relative; and then use absolute positioning to position the shadow things: http://jsfiddle.net/bpma9ko4/
Here the relevant parts:
.shadow-box {
width: 45%;
margin: 0 1% 0 0;
height: 100%;
transition: all 0.2s ease-in-out;
cursor: pointer;
display: inline-block;
position: relative;
}
.shadow-box:before, .shadow-box:after {
content: '';
z-index: 1;
position: absolute;
width: 40%;
height: 110px;
background: red;
transform: skew(-10deg) rotate(-6deg);
transition: all 0.2s ease-in-out;
top: 20px;
left: 20px;
}
.shadow-box:after {
transform: skew(10deg) rotate(6deg);
right: 20px;
left: auto;
}
In your example, when I removed the translates, the red box on the right went underneath the image (on a new line) and then you tried dragging it up with translates, but to me it is a much more direct way if you just place it over the image to begin with, using the top/left/right attributes.
Note: My example is simplified, it doesn't have shadows and other things, it's cut down to the parts relevant to the question.
The whole code:
html, body {
width: 100%;
height: 100%;
}
.row {
height: 160px;
width: 80%;
margin: 0 auto 60px;
display: block;
img:nth-of-type(1) {
content: url(http://marshall.org/wp-content/themes/marshall/img/featured-space-policy.jpg);
}
img:nth-of-type(2) {
content: url(http://i.dailymail.co.uk/i/pix/2014/09/04/1409790551890_wps_28_Astronaut_Reid_Wiseman_po.jpg);
}
img:nth-of-type(3) {
content: url(http://cdn2.collective-evolution.com/assets/uploads/2014/08/life_in_space-728x400.jpg);
}
img:nth-of-type(4) {
content: url(http://s.ngm.com/2007/10/space-travel/img/space_feature.jpg);
}
}
img {
width: 100%;
margin: 0 1% 0 0;
height: 100%;
transition: all 0.2s ease-in-out;
cursor: pointer;
}
.shadow-box {
width: 45%;
margin: 0 1% 0 0;
height: 100%;
transition: all 0.2s ease-in-out;
cursor: pointer;
display: inline-block;
position: relative;
}
.shadow-box:before, .shadow-box:after {
content: '';
z-index: 1;
position: absolute;
width: 40%;
height: 110px;
background: red;
transform: skew(-10deg) rotate(-6deg);
transition: all 0.2s ease-in-out;
top: 20px;
left: 20px;
}
.shadow-box:after {
transform: skew(10deg) rotate(6deg);
right: 20px;
left: auto;
}
.shadow-box:hover:before, .shadow-box:hover:after {
box-shadow: 0 20px 20px lighten($black, 40%);
}
<h2>Shadow #3</h2>
<div class="row shadow-3">
<div class="shadow-box">
<img src="http://placehold.it/466x180">
</div>
<div class="shadow-box">
<img src="http://placehold.it/466x180">
</div>
<div class="shadow-box">
<img src="http://placehold.it/466x180">
</div>
<div class="shadow-box">
<img src="http://placehold.it/466x180">
</div>
</div>

Related

Adding a transition to a card

.grid_content {
max-width: 700px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
display: block;
}
.caption {
position: absolute;
z-index: 1;
bottom: 0;
padding: 30px;
colour: white;
width: 100%;
height: 100%;
opacity: 0;
transition: 1s;
}
h4 {
font-family: var(--font-style-custom);
letter-spacing: 3px;
}
p {
margin: 5px;
}
h4,
p {
position: relative;
top: 85px;
}
.caption:hover {
transition: 1s;
opacity: 1;
background: linear-gradient(hsl(0, 0%, 100%, 0.1), hsl(0 0% 0% / 0.6));
}
<div class="grid_content">
<img src="https://img.freepik.com/free-psd/box-packaging-mockup-isolated_23-2149208917.jpg?w=740&t=st=1663223199~exp=1663223799~hmac=6f0288bfcdf858b4908269c5406636c1f3c0bfca3e70041f67d9adc5b0be7dea" alt="Brading image">
<div class="caption">
<h4>Laynard</h4>
<p>Brand-identity</p>
</div>
</div>
Whenever I hover on the image, I want the background color to slowly transition in and out, but here it only transitions in and disappears when I don't hover, I've added transition to the caption div element in the card and it still didn't work
As initially the opacity of the element with the class caption's opacity is set to 0, it's recommended to include the background property in .caption {...} rather than in .caption:hover {...}.
Additionally, remove the transition property in .caption:hover as it's useless.
The issue with your implementation is that when the cursor hovers over the element, the background property is set, and when the cursor is not longer hovering over the element, the background property is reset and the transiton property doesn't get applied to it.
.grid_content {
max-width: 700px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
display: block;
}
.caption {
position: absolute;
z-index: 1;
bottom: 0;
padding: 30px;
colour: white;
width: 100%;
height: 100%;
opacity: 0;
transition: 1s;
background: linear-gradient(hsl(0, 0%, 100%, 0.1), hsl(0 0% 0% / 0.6));
}
h4 {
font-family: var(--font-style-custom);
letter-spacing: 3px;
}
p {
margin: 5px;
}
h4,
p {
position: relative;
top: 85px;
}
.caption:hover {
opacity: 1;
}
<div class="grid_content">
<img src="https://img.freepik.com/free-psd/box-packaging-mockup-isolated_23-2149208917.jpg?w=740&t=st=1663223199~exp=1663223799~hmac=6f0288bfcdf858b4908269c5406636c1f3c0bfca3e70041f67d9adc5b0be7dea" alt="Brading image">
<div class="caption">
<h4>Laynard</h4>
<p>Brand-identity</p>
</div>
</div>
Move your background style from .caption:hover to .caption
You already made the transition of opacity
.grid_content {
max-width: 700px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
display: block;
}
.caption {
position: absolute;
z-index: 1;
bottom: 0;
padding: 30px;
colour: white;
width: 100%;
height: 100%;
opacity: 0;
transition: 1s;
background: linear-gradient(hsl(0, 0%, 100%, 0.1), hsl(0 0% 0% / 0.6));
}
h4 {
font-family: var(--font-style-custom);
letter-spacing: 3px;
}
p {
margin: 5px;
}
h4,
p {
position: relative;
top: 85px;
}
.caption:hover {
transition: 1s;
opacity: 1;
}
<div class="grid_content">
<img src="https://img.freepik.com/free-psd/box-packaging-mockup-isolated_23-2149208917.jpg?w=740&t=st=1663223199~exp=1663223799~hmac=6f0288bfcdf858b4908269c5406636c1f3c0bfca3e70041f67d9adc5b0be7dea" alt="Brading image">
<div class="caption">
<h4>Laynard</h4>
<p>Brand-identity</p>
</div>
</div>

CSS flexbox adds random spacing between elements

I have a problem. I want to use a animated checkbox and tried adding it to my code. The first problem I have is that the checkbox was floating a row above the <p> tag. For that I tried to create a flexbox with align-items: center;, but that results in a row that is aligned for some reason to the right side and the checkbox is still not at the same height as the <p> tag.
Here is the code snippet:
._checkbox
{
display: none;
}
label
{
width: 20px;
height: 20px;
margin: 0 auto;
background-color: #3f97fc;
transform: translateY(-50%);
border-radius: 50%;
cursor: pointer;
transition: 0.2s ease transform, 0.2s ease background-color, 0.2s;
overflow: hidden;
z-index: 1;
}
label:before
{
content: "";
position: absolute;
top: 50%;
right: .5%;
left: 0;
width: 15px;
height: 15px;
margin: 0 auto;
background-color: #fff;
transform: translateY(-50%);
border-radius: 50%;
transition: 0.2s ease width, 0.2s ease height;
}
#tick_mark
{
position: absolute;
top: 3px;
right: 0;
left: -11px;
width: 12px;
height: 10px;
margin: 0 auto;
margin-left: 14px;
transform: rotateZ(-40deg);
}
#tick_mark:before, #tick_mark:after
{
content: "";
position: absolute;
background-color: #fff;
border-radius: 2px;
opacity: 0;
transition: 0.2s ease transform, 0.2s ease opacity;
}
#tick_mark:before
{
left: 0;
bottom: 0;
width: 3px;
height: 8px;
transform: translateY(-68px)
}
#tick_mark:after
{
left: 0;
bottom: 0;
width: 100%;
height: 3px;
transform: translateX(78px)
}
._checkbox:checked + label
{
background-color: #07d410;
}
._checkbox:checked + label:before
{
width: 0;
height: 0;
}
._checkbox:checked + label #tick_mark:before, ._checkbox:checked + label #tick_mark:after
{
transform: translate(0);
opacity: 1;
}
.checkbox_container
{
display: flex;
align-items: center;
space-between: 0px
}
.teskt {
padding: 0px;
}
<div class="option 0, checkbox_container"><input type="checkbox" id="Air Quality" class="_checkbox"><label for="Air Quality"><div id="tick_mark"></div></label><p class="tekst"> Air Quality - 7 Project(s)</p></div>
So just to be clear... I want the checkbox next to the <p> tag and the height of them needs to be on the same level. Also, the content needs to be aligned to the right side!
Can someone tell me how to achieve this?
Everything aligned to left, vertically on the same level, like this?
I removed transform from label, not sure why you had it there and set it to position relative and replaced margin with margin right for spacing. On the flex container I updated it to
.checkbox_container {
display: flex;
align-items: center; // vertically centers flex items
}
._checkbox {
display: none;
}
label {
width: 20px;
height: 20px;
background-color: #3f97fc;
position: relative;
border-radius: 50%;
cursor: pointer;
transition: 0.2s ease transform, 0.2s ease background-color, 0.2s;
overflow: hidden;
z-index: 1;
margin-right: 10px;
}
label:before {
content: "";
position: absolute;
top: 50%;
right: .5%;
left: 0;
width: 15px;
height: 15px;
margin: 0 auto;
background-color: #fff;
transform: translateY(-50%);
border-radius: 50%;
transition: 0.2s ease width, 0.2s ease height;
}
#tick_mark {
position: absolute;
top: 3px;
right: 0;
left: -11px;
width: 12px;
height: 10px;
margin: 0 auto;
margin-left: 14px;
transform: rotateZ(-40deg);
}
#tick_mark:before,
#tick_mark:after {
content: "";
position: absolute;
background-color: #fff;
border-radius: 2px;
opacity: 0;
transition: 0.2s ease transform, 0.2s ease opacity;
}
#tick_mark:before {
left: 0;
bottom: 0;
width: 3px;
height: 8px;
transform: translateY(-68px)
}
#tick_mark:after {
left: 0;
bottom: 0;
width: 100%;
height: 3px;
transform: translateX(78px)
}
._checkbox:checked+label {
background-color: #07d410;
}
._checkbox:checked+label:before {
width: 0;
height: 0;
}
._checkbox:checked+label #tick_mark:before,
._checkbox:checked+label #tick_mark:after {
transform: translate(0);
opacity: 1;
}
.checkbox_container {
display: flex;
align-items: center;
}
.teskt {
padding: 0px;
}
<div class="option 0, checkbox_container">
<input type="checkbox" id="Air Quality" class="_checkbox">
<label for="Air Quality">
<span id="tick_mark"></span>
</label>
<p class="tekst"> Air Quality - 7 Project(s)</p>
</div>

Text on image on hover affected by filter brightness

I'm trying to create images with texts on them but when it hovers the brightness of the image goes down yet it shouldn't affect the text. Can I achieve that just with css?
#mixin easeOut {
transition: all 0.3s ease-out;
}
.team-pics {
display: flex;
flex-wrap: wrap;
div {
width: 33%;
img {
display: block;
width: 100%;
padding: 1rem;
#include easeOut;
}
.team-pic-caption {
opacity: 0;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 1rem;
#include easeOut;
color: #fff;
}
&:hover {
filter: brightness(.5);
.team-pic-caption {
opacity: 1;
}
}
}
}
<div class="team-pics">
<div>
<img src="https://images.unsplash.com/photo-1515550833053-1793be162a45?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=31a23f7d7e8b0e43153da6565aa7157e&auto=format&fit=crop&w=500&q=60" />
<div class="team-pic-caption">
<h3>Josh Garwood</h3>
<p>Co-Founder and Technical Director</p>
</div>
</div>
<div>
<img src="https://images.unsplash.com/photo-1513267096918-a2532362a784?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=f971c866a1e22a858a0c2ea72274838c&auto=format&fit=crop&w=500&q=60" />
<div class="team-pic-caption">
<h3>Jason Benjamin</h3>
<p>Co-Founder and Marketing Director</p>
</div>
</div>
</div>
https://codepen.io/yubind/pen/mGWQBr
I have a few potential solutions for you
Here is the first (background will blur, but text will remain the same, code is adaptable to your needs of course):
#imgtext {
position: relative;
float: left;
width: 300px;
padding: 30px;
margin: 15px;
border-radius: 20px;
height: 150px;
overflow: hidden;
}
#imgtext:after {
content: '';
display: block;
position: absolute;
z-index: -1;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: url(https://upload.wikimedia.org/wikipedia/en/e/e4/Blank_cd.png) no-repeat center;
background-size: cover;
}
#imgtext:hover:after {
-webkit-filter: blur(5px);
}
p {
font-size: 3em;
color: red;
text-align: center;
}
<div>
<div id="imgtext">
<p>Hello<p>
</div>
</div>
Another is outlined in this fiddle (the text only appears on hover, when the image fades)
.wrapper {
position: relative;
padding: 0;
width: 150px;
display: block;
}
.text {
position: absolute;
top: 0;
color: #f00;
background-color: rgba(255, 255, 255, 0.8);
width: 150px;
height: 150px;
line-height: 1em;
text-align: center;
z-index: 10;
opacity: 0;
-webkit-transition: all .5s ease;
-moz-transition: all .5s ease;
-o-transition: all .5s ease;
transition: all .5s ease;
}
.text img {
top: 20px;
position: relative;
}
.text:hover {
opacity: 1;
}
}
img {
z-index: 1;
}
<a href="#" class="wrapper">
<span class="text">
<img src="http://prologicit.com/wp-content/uploads/2012/07/160px-Infobox_info_icon_svg-150x150.png" width="30" height="30"><br><br><br>
"Photo"<br>
Made:1999<br>
By: A. Miller<br>
150x150px
</span>
<img src="http://lorempixel.com/150/150">
</a>
I like this animate opacity fiddle but it may be over what you're looking for...

How to center horizontally a position: absolute elment on a position: fixed container

I need to center horizontally a button with aboslute position (because it must keep on top when to click and launch overlay and click to close overlay) on a position fixed topbar, here is the code:
.topbar {
text-align: center;
min-width: 100%;
height: 50px;
background-color: #29343a;
position: fixed;
top: 0;
}
.button {
display: inline-block;
margin-right: auto;
margin-left: auto;
width: 60px;
height: 50px;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
z-index: 100;
position: absolute;
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(153,204,51,0.9);
}
Thats is just the css of the three parts, the website is more complex but i think that 3 parts are the key. the topbar must be fixed on top, the buton have to be centered into the topbar div, and the overlay launch and the buttop keeps on top of the overlay.
What is working: the overlay works fine and the button keeps on top but its not horizontally centered on the topbar.
How i can hack this?
You could to the left:0 and right:0 trick.
.button {
display: inline-block;
margin-right: auto;
margin-left: auto;
width: 60px;
height: 50px;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
z-index: 100;
position: absolute;
left: 0; /*added*/
right: 0; /*added*/
}
Or do the left:50% with negative left margin (half width).
.button {
display: inline-block;
width: 60px;
height: 50px;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
z-index: 100;
position: absolute;
left: 50%; /*added*/
margin-left: -30px; /*added*/
}
Or use CSS3 transform.
.button {
display: inline-block;
width: 60px;
height: 50px;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
z-index: 100;
position: absolute;
left: 50%; /*added*/
transform: translateX(-50%); /*added*/
}
Based on the information you provided this is what I could come up with:
/* CSS */
.topBar {
position:fixed;
top:0;
left:0;
width:100%;
height:auto;
background-color:#29343a;
}
.overlay {
display:none;
width: 100%;
background: rgba(153,204,51,0.9);
margin:0;
}
.button, .button:active, .button:visited, .button:hover {
display: block;
position:relative;
text-align:center;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
margin:0 auto;
padding:10px;
}
.topBar:hover > .overlay {
display:block;
}
And I added some html because you didn't provide any:
<!-- HTML -->
<div class="topBar">
Button
<div class="overlay">
<p>Some text shows when button hover</p>
</div>
</div>
JSFIDDLE: https://jsfiddle.net/0napm6y3/
Here is the complete code of this component made on react:
This is the react component, the overlay launch is the overlay var, the other one is for one animation on the button:
var React = require('react');
var StatusBarButtonView = React.createClass({
getInitialState: function() {
return {cliked: false};
},
handleClick: function(event) {
this.setState({cliked: !this.state.cliked});
},
render: function() {
var fondo = this.state.cliked ? 'active' : '';
var overlay = this.state.cliked ? 'open' : '';
return (
<div>
<div className={"aui-profit-statusbar-button-container " + (fondo)} onClick={this.handleClick}>
<img src="images/aui-navbar-element-icon-cross.png" className={"rotate " + (fondo)}/>
</div>
<div className={"overlay overlay-slidedown " + (overlay)}>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Work</li>
<li>Clients</li>
<li>Contact</li>
</ul>
</nav>
</div>
</div>
);
}
});
module.exports = StatusBarButtonView;
Here is the topbar scss:
.aui-profit-statusbar-container {
text-align: center;
min-width: 100%;
height: 50px;
background-color: #29343a;
position: fixed;
top: 0;
}
Here is the button scss:
.aui-profit-statusbar-button-container {
display: inline-block;
margin-right: auto;
margin-left: auto;
width: 60px;
height: 50px;
cursor: pointer;
background-color: #00c1e2;
border-bottom: 2px solid #00a8c6;
z-index: 100;
position: absolute;
left: 0;
right: 0;
&:hover {
background-color: #56d9f6;
}
&.active {
background-color: #ff4b39;
border-bottom: 2px solid #e43f30;
}
.rotate {
margin-top: 13px;
width: 23px;
height: 23px;
-webkit-transition-duration: 0.2s;
-moz-transition-duration: 0.2s;
-ms-transition-duration: 0,2s;
-o-transition-duration: 0.2s;
transition-duration: 0.2s;
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
-ms-transition-property: -ms-transform;
-o-transition-property: -o-transform;
transition-property: transform;
}
.active {
-webkit-transform: rotate(135deg);
-moz-transform: rotate(135deg);
-ms-transform: rotate(135deg);
-o-transform: rotate(135deg);
transform: rotate(135deg);
}
}
Here is the overlay css:
/* Overlay style */
.overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(153,204,51,0.9);
}
/* Overlay closing cross */
.overlay .overlay-close {
width: 80px;
height: 80px;
position: absolute;
right: 20px;
top: 20px;
overflow: hidden;
border: none;
background: url(../img/cross.png) no-repeat center center;
text-indent: 200%;
color: transparent;
outline: none;
z-index: 100;
}
/* Menu style */
.overlay nav {
text-align: center;
position: relative;
top: 50%;
height: 60%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
.overlay ul {
list-style: none;
padding: 0;
margin: 0 auto;
display: inline-block;
height: 100%;
position: relative;
}
.overlay ul li {
display: block;
height: 20%;
height: calc(100% / 5);
min-height: 54px;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.overlay ul li a {
font-size: 54px;
font-weight: 300;
display: block;
color: #fff;
-webkit-transition: color 0.2s;
transition: color 0.2s;
}
.overlay ul li a:hover,
.overlay ul li a:focus {
color: #e3fcb1;
}
/* Effects */
.overlay-slidedown {
visibility: hidden;
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
-webkit-transition: -webkit-transform 0.4s ease-in-out, visibility 0s 0.4s;
transition: transform 0.4s ease-in-out, visibility 0s 0.4s;
}
.overlay-slidedown.open {
visibility: visible;
-webkit-transform: translateY(0%);
transform: translateY(0%);
-webkit-transition: -webkit-transform 0.4s ease-in-out;
transition: transform 0.4s ease-in-out;
}
#media screen and (max-height: 30.5em) {
.overlay nav {
height: 70%;
font-size: 34px;
}
.overlay ul li {
min-height: 34px;
}
}
Now it works perfectly, thanks to all.
Next thing i have to do is separate overlay of buttom component. and keep it running, but im wondering to to pass the action to one component to another.... i have to learn more about react.js

CSS3 different background color element coming from top

Right now I'm doing this to animate an element background color.
<style>
.container{
padding: 30px;
}
.element {
position: relative;
font-size: 20px;
line-height: 20px;
background-color: #c00;
display: inline-block;
overflow: hidden;
}
.element div {
position: absolute;
top: -20px;
left: 0;
background-color: #0c0;
transition:top 0.5s ease;
}
.element:hover div {
top: 0px;
transition:top 0.5s ease;
}
</style>
<div class="container">
<div class="element">some text<div>some text</div></div>
</div>
JsFiddle demo.
Is there any "cleaner" way to have the same animation? Right now I'm duplicating my content to achieve this.
You can use pseudo elements for this, and not have to duplicate any content:
It's basically moving one pseudo from above the element, and bringing it down over the element on the hover
div {
position: relative;
display: inline-block;
overflow: hidden;
}
div:before,
div:after {
content: "";
position: absolute;
left: 0;
height: 100%;
width: 100%;
transition: all 0.6s;
z-index: -1;
}
div:before {
top: 0;
background: red;
}
div:after {
top: -100%;
background: green;
}
div:hover:before {
top: 100%;
}
div:hover:after {
top: 0;
}
<div>Text? Why would you ever want text?</div>
If you want the text to 'move' as well, you can do something similar:
div {
position: relative;
display: inline-block;
overflow: hidden;
height:20px;
width:300px;
}
div:before,
div:after {
content: attr(data-text);
position: absolute;
left: 0;
height: 100%;
width: 100%;
transition: all 0.6s;
z-index: -1;
}
div:before {
top: 0;
background: red;
}
div:after {
top: -100%;
background: green;
}
div:hover:before {
top: 100%;
}
div:hover:after {
top: 0;
}
<div data-text="Text? Why would you ever want text?"></div>
Note: canIuse suggests it is widely supported (bit I admit only tested in latest chrome, so only going by this for cross browser). However, This may affect SEO, and so I would be reluctant to use this in production.
If you just wanted the 'upper' element to flow over the top of the text (instead of 'lower' text scrolling as well), You could do:
div {
position: relative;
display: inline-block;
overflow: hidden;
height: 20px;
width: 300px;
background: red;
}
div:before {
content: attr(data-text);
position: absolute;
left: 0;
height: 100%;
width: 100%;
transition: all 0.6s;
top: -100%;
background: green;
}
div:hover:before {
top: 0;
}
<div data-text="The text I always wanted">The text I always wanted</div>
You could do it with background-position
Set a linear-gradient to 50% of each of the background colors and set the background size to be 200% of the actual div.
Then animate it and move the background 100% up. Like this:
.container {
padding: 30px;
}
.element {
position: relative;
font-size: 20px;
line-height: 20px;
background-color: #c00;
display: inline-block;
overflow: hidden;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, #c00 50%, #0c0 50%);
}
.element:hover {
background-position: 0 -100%;
transition: background-position 1s;
}
<div class="container">
<div class="element">some text</div>
</div>
This cuts out the need for any duplicate content in either the css or the html.
Yes, you can use pseudo element :before and get the text with attribute like:
<div class="container">
<div class="element" data-text="some text">some text</div>
</div>
And css:
.container{
padding: 30px;
}
.element {
position: relative;
font-size: 20px;
line-height: 20px;
background-color: #c00;
display: inline-block;
overflow: hidden;
}
.element:before {
content: attr(data-text);
position: absolute;
top: -20px;
left: 0;
background-color: #0c0;
transition:top 0.5s ease;
}
.element:hover:before {
top: 0px;
transition:top 0.5s ease;
}
http://jsfiddle.net/Pik_at/g3Lxrou4/3/
just similar to jbutler483, but using just a single pseudo class. FIDDLE
.container {
padding: 30px;
}
.element {
position: relative;
font-size: 20px;
line-height: 20px;
background-color: #c00;
display: inline-block;
transition: top 0.5s ease;
overflow: hidden;
}
.element:after {
position: absolute;
top: -60px;
content: 'some text';
font-size: 20px;
line-height: 20px;
left: 0;
display: inline-block;
background-color: #0c0;
transition: top 0.5s ease;
}
.element:hover:after {
top: 0px;
}
<div class="element">some text</div>