I'm trying to draw a border with border-radius: 8px;. It perfectly draws symmetrical border without border-radius but messed up with it. What am I doing wrong here?
setTimeout(function(){
document.getElementsByClassName('border')[0].classList.add('animate-border');
},100)
body {
background: white;
}
.main-container {
position:absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
width: 300px;
height: 460px;
background: ;
}
.border:before {
border:2px solid black;
border-radius: 8px;
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 0;
border-top: 0;
border-left: 0;
pointer-events: none;
overflow: hidden;
opacity: 0;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:before {
opacity: 1;
height: 100%;
width: 100%;
transition: opacity 0s ease,width 0.5s ease, height 0.5s 0.5s ease;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border:after {
border: 2px solid black;
border-radius: 8px;
content: '';
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
border-bottom: 0;
border-right: 0;
opacity: 0;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:after {
opacity: 1;
height: 100%;
width: 100%;
overflow: hidden;
transition: opacity 0s 1s ease,width 0.5s 1s ease, height 0.5s 1.5s ease;
transform: rotateZ(0) rotate(0);
}
<div class='main-container border'></div>
CSS:
body {
background: white;
}
.main-container {
position:absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
width: 300px;
height: 460px;
background: ;
}
.border:before {
border:2px solid black;
border-radius: 8px;
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 0;
border-top: 0;
border-left: 0;
pointer-events: none;
overflow: hidden;
opacity: 0;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:before {
opacity: 1;
height: 100%;
width: 100%;
transition: opacity 0s ease,width 0.5s ease, height 0.5s 0.5s ease;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border:after {
border: 2px solid black;
border-radius: 8px;
content: '';
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
border-bottom: 0;
border-right: 0;
opacity: 0;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:after {
opacity: 1;
height: 100%;
width: 100%;
overflow: hidden;
transition: opacity 0s 1s ease,width 0.5s 1s ease, height 0.5s 1.5s ease;
transform: rotateZ(0) rotate(0);
}
First of all, you may apply box-sizing: border-box in all elements (and pseudo-elements) to make the alignment easier. It makes the browser count the border on width and height calculation. That solves your misalignment problem.
Second, since you're resizing the element, the rounded corners get stretched in the middle of the animation. I see no easy way prevent that from happening. But you can disguise it by also animating the right property of the :after pseudo-element, like I did below. That and a faster timing may get you there with your animation.
BTW, it would be more performant if you animated transform: scaleX(...) scaleY(...) instead of width and height, because they're GPU accelerated.
setTimeout(function(){
document.getElementsByClassName('border')[0].classList.add('animate-border');
},100)
body {
background: white;
}
*, *:before, *:after { /* Applies to ALL elements and pseudo-elements */
box-sizing: border-box;
}
.main-container {
position:absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
width: 300px;
height: 160px;
background: ;
}
.border:before {
border:2px solid black;
border-radius: 8px;
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 0;
border-top: 0;
border-left: 0;
pointer-events: none;
overflow: hidden;
opacity: 0;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:before {
opacity: 1;
height: 100%;
width: 100%;
transition: opacity 0s ease,width 0.5s ease, height 0.5s 0.5s ease;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border:after {
border: 2px solid black;
border-radius: 8px;
content: '';
position: absolute;
top: 0;
right: 6px; /* a little offset to hide the squared edge */
width: 0;
height: 0;
border-bottom: 0;
border-right: 0;
opacity: 0;
overflow: hidden;
transform: rotateZ(0) rotate(0);
}
.border.animate-border:after {
opacity: 1;
height: 100%;
width: 100%;
right: 0; /* the wanted right position */
overflow: hidden;
transition: opacity 0s 1s ease,width 0.5s 1s ease, height 0.5s 1.5s ease,right 1s 1s ease; /* Animated 'right' so it slowly gets back to its position */
transform: rotateZ(0) rotate(0);
}
<div class='main-container border'></div>
PS.: I changed the box height to make it fit inside the snippet here.
You just need to specify properties below to pseudo elements because they are position absolute
Add top:0 to .border:before css and add left:0 to .border:after css
Related
I have a hover animation that I have created with CSS. When the user hovers over the link the underline transitions from left to right changing the colour from black to grey. Currently as you would expect when the user moves their mouse off the link the transition reverses to start state.
I wondered if it is possible to prevent this reverse transition and instead fade the underline back to the colour black (the original start state)?
Here is a jsfiddle to work with.
Any suggestions/advise would be most welcome.
a.btn--tertiary {
padding-left: 0;
padding-right: 0;
background-color: transparent;
color: #000;
border: 0;
position: relative;
padding-bottom: 5px;
text-transform: uppercase;
text-decoration: none;
font-size: 40px;
}
.btn--tertiary:before {
content: '';
height: 2px;
right: 0;
width: 100%;
background: #000;
position: absolute;
bottom: 0;
opacity: 1;
transition: width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0s;
z-index: 2;
border-left: 10px solid transparent;
}
.btn--tertiary:after {
content: '';
height: 2px;
left: 0;
right: auto;
width: 0%;
background: grey;
position: absolute;
bottom: 0;
transition: width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0.1s;
z-index: 3;
}
.btn--tertiary:hover:before,
.btn--tertiary:focus:before {
width: 0%;
border-left: 20px solid $white;
}
.btn--tertiary:hover::after,
.btn--tertiary:focus::after {
right: 0;
width: 100%;
}
Yes, it is indeed. The trick is to make the width transition out take 0s with a delay of 1s.
html,
body {
margin: 0;
padding: 0;
}
a.btn--tertiary {
padding-left: 0;
padding-right: 0;
background-color: transparent;
color: #000;
border: 0;
position: relative;
padding-bottom: 5px;
text-transform: uppercase;
text-decoration: none;
font-size: 40px;
}
.btn--tertiary::before {
content: '';
height: 2px;
right: 0;
width: 100%;
background: #000;
position: absolute;
bottom: 0;
transition: width 0s;
z-index: 2;
border-left: 10px solid transparent;
}
.btn--tertiary::after {
content: '';
height: 2px;
left: 0;
right: auto;
width: 0%;
background: grey;
position: absolute;
bottom: 0;
opacity: 0;
transition: opacity .5s, width 0s .5s;
z-index: 3;
}
.btn--tertiary:hover:before,
.btn--tertiary:focus:before {
width: 0%;
border-left: 20px solid $white;
transition: width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0s;
}
.btn--tertiary:hover::after,
.btn--tertiary:focus::after {
right: 0;
width: 100%;
opacity: 1;
transition: opacity 0s, width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0.1s;
}
Button
Fiddle.
You can try like below. Check the comments for the details:
a.btn--tertiary {
color: #000;
position: relative;
padding-bottom: 5px;
display:inline-block;
text-decoration:none;
overflow:hidden;
font-size: 40px;
}
.btn--tertiary:before,
.btn--tertiary:after {
content: '';
height: 2px;
position: absolute;
bottom: 0;
}
.btn--tertiary:before {
right: 0;
width: 100%;
background: #000;
border-left: 20px solid #fff;
transition:
background 2s cubic-bezier(0.100, 0.600, 0.350, 1.000); /* transition the background on mouseout*/
}
.btn--tertiary:after {
left: 0;
width: 0%;
background: red;
}
.btn--tertiary:hover:before,
.btn--tertiary:focus:before {
width: 0%;
background: red;
transition:
width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0s, /* visible transition of width on hover */
background 0s 1s; /* no transition but a background change after 1s */
}
.btn--tertiary:hover::after,
.btn--tertiary:focus::after {
right: 0;
width: 100%;
transition:
width 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0.1s; /* visible transition of width on hover */
}
Button
I hope this would help, please see the example below.
div {
text-align: center;
margin-top: 20px;
}
.btn--tertiary {
text-decoration: none;
font-family: sans-serif;
text-transform: uppercase;
display: inline-block;
position: relative;
overflow: hidden;
font-size: 45px;
color: black;
}
.btn--tertiary::before {
position: absolute;
content: '';
width: 100%;
height: 3px;
bottom: 0;
left: 0;
background: gray;
transform: scale(0, 1);
transform-origin: right;
transition: transform 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0s;
}
.btn--tertiary:hover::before {
transform: scale(1, 1);
transform-origin: left;
transition: transform 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) .1s;
}
.btn--tertiary::after {
position: absolute;
content: '';
width: 100%;
height: 3px;
bottom: 0;
right: 0;
background: black;
transform: scale(1, 1);
transform-origin: left;
transition: transform 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) .1s;
}
.btn--tertiary:hover::after {
transform: scale(0, 1);
transform-origin: right;
transition: transform 1s cubic-bezier(0.100, 0.600, 0.350, 1.000) 0s;
}
<div>
Button
</div>
I would like to animate two borders on hover specifically border-left and border-top. After doing some research it does not seem you can actually "animate" the borders themselves so you have to create a "line" which on hover should have its width set to 100% to have the same effect.
I know how to do this with underlining menu items, but I would like to do it with this box I'm trying to create.
Specifically on hover (while maintaining the css effects already written up)
1) border-left should extend to the top and right after that-> 2) border-top extending from the left to the right.
Also was wondering how I can choose which borders to extend if I don't want to to just do border-left or border-top.
This is my box thus far (unfortunately nothing with animating borders):
CSS:
#txt{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%, -50%);
font-size:2vw;
}
#box{
position:fixed;
top:25%;
left:25%;
height:20vw;
width:20vw;
border-right: 2px solid deepskyblue;
border-bottom: 2px solid deepskyblue;
background-color:black;
color:ghostwhite;
}
#box:hover{
color:deepskyblue;
transition: color 0.25s ease;
}
#box:after{
content:"";
position:absolute;
bottom: 0;
left: 0;
width:100%;
height:100%;
transform: scale(0, 0);
transform-origin:bottom right;
background: ghostwhite;
z-index: -1;
transition: transform 0.25s ease;
}
#box:hover::after{
transform: scale(1, 1);
color:deepskyblue;
}
HTML:
<div id="box">
<span id="txt">TEXT</span>
</div>
You can make the #txt element as large as the parent box and then use pseudo-element on that to make "borders" and animate the dimensions of those pseudo-elements.
If you add a transiton-delay in I think you can get the effect you are after.
#txt {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
#box {
font-size: 2vw;
position: fixed;
top: 1em;
left: 40vw;
height: 20vw;
width: 20vw;
background-color: black;
color: ghostwhite;
}
#box:hover {
color: deepskyblue;
transition: color 0.25s ease;
}
#box:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
transform: scale(0, 0);
transform-origin: bottom right;
background: ghostwhite;
z-index: -1;
transition: transform 0.25s ease;
}
#box:hover::after {
transform: scale(1, 1);
color: deepskyblue;
}
#txt::before {
content: "";
position: absolute;
z-index: 2;
left: 0;
bottom: 0;
height: 0;
}
#txt::before {
width: 0;
border-left: 2px solid deepskyblue;
transition: height .25s .5s ease;
}
#txt:hover::before {
height: 100%;
}
#txt::after {
content: "";
position: absolute;
width: 0%;
top: 0;
left: 0;
border-top: 2px solid deepskyblue;
transition: width 0.25s .75s ease;
}
#txt:hover::after {
width: 100%;
}
<div id="box">
<span id="txt">TEXT</span>
</div>
I've created a Slanted Div, however I ran into problem I cannot solve, I've googled this but did not find any answers.
body {
background: black;
}
#slantedwrapper {
overflow: hidden;
margin-left: 50px;
}
#slanted {
display: inline-block;
/* margin-right:-4px; */
width: 400px;
margin-left: -45px;
/* background-image: url("http://www.keenthemes.com/preview/conquer/assets/plugins/jcrop/demos/demo_files/image2.jpg"); */
}
#slanted a {
position: relative;
background-color: #1d1d1d;
/* background-image: url("http://www.keenthemes.com/preview/conquer/assets/plugins/jcrop/demos/demo_files/image2.jpg"); */
box-sizing: border-box;
background-size: cover;
/* padding:1em; */
display: block;
transform: skewX(-30deg);
width: 100%;
min-height: 3.5em;
text-align: center;
border-right: 5px solid #20c397;
height: 150px;
/* line-height: 110px; */
overflow: hidden;
}
#slanted span {
color: white;
position: absolute;
box-sizing: border-box;
transform: skewX(30deg);
left: 0;
width: 100%;
/* height: 150px; */
/* background-image: url("http://www.keenthemes.com/preview/conquer/assets/plugins/jcrop/demos/demo_files/image2.jpg"); */
}
}
}
.current a {
background:#70cb00;
}
#slanted a img {
transform: skewX(30deg);
overflow: hidden;
margin-top: -20px;
padding-top: 0px;
width: 123%;
height: 123%;
margin-left: -50px;
opacity: 0.6;
-webkit-transition: opacity 0.3s linear 0s;
-o-transition: opacity 0.3s linear 0s;
transition: opacity 0.3s linear 0s;
}
#slanted img:hover {
opacity:1;
}
#caption {
background-color: #333333;
width: 100%;
height: 25px;
display: block;
position: absolute;
bottom: 0;
z-index: 99;
opacity: 0.7;
color: #D2D2D2;
-webkit-transition: background-color 0.3s linear 0s;
-o-transition: background-color 0.3s linear 0s;
transition: background-color 0.3s linear 0s;
}
/*Combination hover effects*/
#slanted:hover #caption {
background-color: #20c397;
opacity:1.0;
}
#slanted:hover img {
opacity:1.0;
}
/* END OFCombo hover effects*/
p.nonskew {
transform: skewX(30deg);
color: White;
margin: 0;
margin-left: 22%;
padding: 1.5%;
text-align: left;
font-size: 0.8em;
}
<div id="slantedwrapper">
<div id="slanted">
<a href="#">
<div id="caption">
<p class="nonskew">A Caption: Description</p>
</div>
<img src="http://www.keenthemes.com/preview/conquer/assets/plugins/jcrop/demos/demo_files/image2.jpg" alt="SLANTED DIV"></a>
</div>
<!--end of wrapper-->
</div>
JSFiddle version
here's the problem:
Hover over the div, it hovers fine, but at the bottom right corner, where nothing is there (where the overflow is hidden) still hovers if you place your mouse over the blank area where the angle begins, how do I solve this into when it hovers- it only applies to shape of the div only?
Thank you
You seem to have the right idea, using both the unskew and intuitive to using the skew, however, something like the below example may work for you:
html {
background: radial-gradient(#222, blue);
height: 100%;
}
div.wrap{
height: 150px;
width: 300px; position: relative;
overflow: hidden;
}
div.innerwrap {
height: 100%;
width: 100%;
transform: skewX(-30deg);
position: absolute;top:0;left:0;
overflow: hidden;
margin-left: -70px;
transition: all 0.4s;
border-right: 5px solid tomato;
cursor:pointer;
}
div.innerwrap:hover span {
background: gold;
}
div.innerwrap:before {
content: "";
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
background: url(http://lorempixel.com/300/300);
transform: skewX(30deg);
transform-origin: top left;
}
div span {
position: absolute;
bottom: 0;
left: 0%;
width: 120%;
transform: skewX(30deg);
background: red;
text-align:center;
transition: all 0.4s;
}
<div class="wrap">
<div class="innerwrap">
<span>TITLE</span>
</div>
</div>
For further information, #Harry has created a wide variety of examples here in which you may find useful.
I have images and a text that is displayed in the center of the image when somebody is hovering over the image.
HTML looks like this:
<article>
<div class="entry-content">
<a href="http://www.linktopost.com">
<h3 class="entry-title">Ring #1</h3>
<img width="620" height="387" src="http://i.telegraph.co.uk/multimedia/archive/02725/scotch-whisky_2725818b.jpg" class="aligncenter" alt="Platzhalter_3">
</a>
</div>
</article>
CSS:
article {
float:left;
width:30%;
display:block;
}
.entry-content {
width: 620px;
margin: 0 auto;
position: relative;
height: 387px;
}
.entry-content:hover .entry-title {
color: #000;
display: table-cell;
background-color: #fff;
opacity: 0.75;
}
.entry-title {
position: absolute;
width: 100%;
height: 100%;
z-index: 9999;
line-height: 387px;
text-align: center;
display: none;
}
article img {
position:absolute;
}
You can see it here:
http://codepen.io/anon/pen/rOXOez
Is there any chance to not use fixed pixel values in the CSS - so that the hover effect is valid and working for any picture? In this example I had to use the width and height of the picture in the CSS to achieve what I wanted.
Thank you!
Solution 1:
Relative/Absolute positioning and center with transform: translate()
https://jsfiddle.net/94efk8kz/
article {
position: relative;
}
.hover-content {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: black;
opacity: 0;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.hover-content h3 {
position: absolute;
top: 50%;
left: 50%;
margin: 0;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
Solution 2:
Flexbox
https://jsfiddle.net/94efk8kz/1/
article {
position: relative;
}
img {
width: 100%;
}
.hover-content {
width: 100%;
height: 100%;
top: 0;
display: flex;
position: absolute;
align-items: center;
justify-content: center;
background: white;
color: black;
opacity: 0;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
Solution 3
CSS Tables
https://jsfiddle.net/94efk8kz/2/
.entry-content a {
float: left;
width:30%;
position: relative;
height: 100%;
}
.hover-content {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
background: white;
color: black;
opacity: 0;
bottom: 0;
right: 0;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.v-align {
display: table;
height: 100%;
margin: 0 auto;
}
.hover-content h3 {
display: table-cell;
vertical-align: middle;
}
Try with these changes
.entry-content {
width: initial;
}
.entry-content:hover .entry-title {
margin: 0;
}
.article img {
display: block;
/* position: absolute; remove this,avoid using positon absolute where you can */
width: 100%;
}
Created a LightBox effect using pure CSS and HTML, no JS. The image appears, but on the right side of the screen, halfway cut off, and partially underneath my Nav bar. Half of the screen is shaded behind the image.
It appears like it would work, aside from it being off-center and behind the navigation. From the code at hand, is there anything that appears it could be doing this? I'd be happy to post more code if necessary. Thank you!
/*Eliminates padding, centers the thumbnail */
body,
html {
padding: 0;
margin: 0;
text-align: center;
float: left;
}
/* Styles the thumbnail */
a.lightbox img {
height: 150px;
border: 3px solid white;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
margin: 94px 20px 20px 20px;
}
/* Styles the lightbox, removes it from sight and adds the fade-in transition */
.lightbox-target {
position: fixed;
top: -100%;
width: 100%;
background: rgba(0, 0, 0, 0.7);
width: 100%;
opacity: 0;
-webkit-transition: opacity .5s ease-in-out;
-moz-transition: opacity .5s ease-in-out;
-o-transition: opacity .5s ease-in-out;
transition: opacity .5s ease-in-out;
overflow: hidden;
clear: both;
}
/* Styles the lightbox image, centers it vertically and horizontally, adds the zoom-in transition and makes it responsive using a combination of margin and absolute positioning */
.lightbox-target img {
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
max-height: 0%;
max-width: 0%;
border: 3px solid white;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
-webkit-transition: .5s ease-in-out;
-moz-transition: .5s ease-in-out;
-o-transition: .5s ease-in-out;
transition: .5s ease-in-out;
}
/* Styles the close link, adds the slide down transition */
a.lightbox-close {
display: block;
width: 50px;
height: 50px;
box-sizing: border-box;
background: white;
color: black;
text-decoration: none;
position: absolute;
top: -80px;
right: 0;
-webkit-transition: .5s ease-in-out;
-moz-transition: .5s ease-in-out;
-o-transition: .5s ease-in-out;
transition: .5s ease-in-out;
}
/* Provides part of the "X" to eliminate an image from the close link */
a.lightbox-close:before {
content: "";
display: block;
height: 30px;
width: 1px;
background: black;
position: absolute;
left: 26px;
top: 10px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
/* Provides part of the "X" to eliminate an image from the close link */
a.lightbox-close:after {
content: "";
display: block;
height: 30px;
width: 1px;
background: black;
position: absolute;
left: 26px;
top: 10px;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
transform: rotate(-45deg);
}
/* Uses the :target pseudo-class to perform the animations upon clicking the .lightbox-target anchor */
.lightbox-target:target {
opacity: 1;
top: 0;
bottom: 0;
}
.lightbox-target:target img {
max-height: 100%;
max-width: 100%;
}
.lightbox-target:target a.lightbox-close {
top: 0px;
}
<div id="gravel-button">
<a class="lightbox" href="#gravel-1">
<h7>Photo & Info</h7>
</a>
</div>
<div class="lightbox-target" id="gravel-1">
<img src="http://www.sbsg.com/wp-content/uploads/2010/02/58minus.jpg">
<a class="lightbox-close"></a>
</div>