Create 'X' with using CSS transform-origin and rotate - html

I have a small issue, I need to rotate 2 spans and create a perfect 'X'.
I've created a JSfiddle for this. Can you guys help me?
I can't seem to get my head around how much should i transform origin...
HTML
<div class="toggle-btn">
<span></span>
<span></span>
</div>
SASS
.toggle-btn {
width: 38px;
height: 19px;
cursor: pointer;
position: relative;
margin-top: 18px;
text-align: center;
&:after {
content: '';
display: block;
clear: both;
}
span {
height: 2px;
margin: 5px 0px;
background: #333;
width: 100%;
display: block;
transition: .15s ease-in;
text-align: center;
&.toggled {
&:nth-of-type(1) {
transform: rotate(-45deg);
transform-origin: 22px 9px;
}
&:nth-of-type(2) {
transform: rotate(45deg);
transform-origin: 20px -5px;
}
}
}
}
and JS
$('.toggle-btn').on('click',function(){
$(this).find('span').toggleClass('toggled');
});

This appears to work. I had to adjust the margin to 4px. The rotation needs to come after the x/y translation because translating after the rotation appears to change the point of origin on which the element is rotating instead of origin of the element. You can observe this behavior by trying a large (100px) x-translation after the rotation.
.toggle-btn {
width: 38px;
height: 19px;
cursor: pointer;
position: relative;
margin-top: 18px;
text-align: center;
overflow: show;
&:after {
content: '';
display: block;
clear: both;
}
span {
height: 2px;
margin: 4px 0px;
background: #333;
width: 38px;
display: block;
transition: .15s ease-in;
text-align: center;
&.toggled {
&:nth-of-type(1) {
transform: translate(0px, 3px) rotate(-45deg);
}
&:nth-of-type(2) {
transform: translate(0px, -3px) rotate(45deg);
}
}
}
}

Related

Transforming and tranisitions in CSS | Transition not working

I have the following css file
body {
font-family: Baskerville;
background: #ecf0f1;
color: #2c3e50;
}
h1 {
margin: 16px 0;
padding-left: 16px;
border-left: 5px solid #e74c3c;
font-family: Baskerville;
font-size: 48px;
}
h3 {
margin: 16px 0;
padding-left: 16px;
color: #cccac4;
}
.container1 {
padding: center;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
}
.container1 .checkbox {
padding: 8px 48px;
margin: 8px;
font-family: Baskerville;
font-size: 25px;
}
input[type="checkbox"]{
display: none;
}
label {
position: relative;
}
label::before {
content: "";
background: url("check-circle.svg");
background-position: center;
background-size: contain;
width: 32px;
height: 32px;
position: absolute;
left: -44px;
top: -8px;
transform: scale(0) rotateZ(180deg);
transition: all 0.4s cubic-bezier(0.54, 0.01, 0, 1.49);
}
input[type="checkbox"]:checked + label::before {
transform: scale(1.0) rotateZ(0deg);
}
label::after {
content: "";
border: 2px solid #27ae60;
width: 24px;
height: 24px;
position: absolute;
left: -42px;
top: 1px;
border-radius: 50%;
}
This is a simple transform and transition where i rotate the img (check-circle.svg) in those 4 curve points of cubic-bezier , whenever it is checked or unchecked after. However the transition and transformation wont work. It will simply not show. Where am i mistaken ?
Are you sure you've placed <label>...</label> immediately after <input type="checkbox"/>? Code seems fine, although I'm not sure what is the purpose of input[type="checkbox"]{ display: none; }. Posting html would be nice too.
Also you can check if provided svg's url is correct. Try to replace it with some other svg url found on internet.
make sure that (label) is a direct next child of (input)

Translate after on hover using CSS

I'm designing the front end of an e-commerce website and while looking through some inspiration I found a really nice effect involving a button and a after on that button, that when hovering over it, the text of the button would go up and at the same time an icon would replace it. You can see what I mean here. I probably won't use this on the project but I got really confused trying to mimic this effect while using Dev Tools, and just ending up with a cart icon on the bottom of the page and would love to know how to create something similar to this.
This is the final result
I almost got to something but I can't seem to make the text and the icon move at the same time, sometimes the icon wouldn't move at all and just the whole button would do, and not the text.
Any ideas on how this could be achieved with CSS? I already went through CodePen to find something similar and I'm not really sure how this effect is called to google it
EDIT: Already tried this code on an with a button class.
.button {
background: none;
font-weight: 600;
line-height: inherit;
margin: 0;
padding: 0 15px;
margin-top: 0;
position: relative;
text-align: center;
vertical-align: top;
-webkit-transition: color 0.15s linear 0s,-webkit-transform 0.3s linear 0s;
text-transform: uppercase;
transition: color 0.15s linear 0s,transform 0.3s linear 0s;
}
.button:hover {
-webkit-transform: translateY(-100%);
-moz-transform: translateY(-100%);
-ms-transform: translateY(-100%);
-o-transform: translateY(-100%);
transform: translateY(-100%);
}
.button:after {
background-color: inherit;
border-color: inherit;
border-style: inherit;
border-width: inherit;
font-size: 18px;
font-weight: 400;
height: auto;
margin: 0;
position: absolute;
left: 0;
top: 100%;
text-align: center;
width: 100%;
-webkit-transform: translateY(0);
transform: translateY(0);
-webkit-animation: none;
animation: none;
}
.button:hover:after {
top: 150%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
Here is a simple example using a psuedo element and font-awesome icon
.btn {
background-color: turquoise;
border-radius: 10px;
color: white;
padding: 5px 10px;
position: relative;
overflow: hidden;
height: 20px;
display: inline-block;
transition: all .3s;
}
.btn span {
position: relative;
top: 0;
transition: all .3s;
}
.btn::after {
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f217";
position: absolute;
left: 50%;
transform: translatex(-50%);
top: 40px;
transition: all .3s;
font-size: 20px;
}
.btn:hover {
background-color: blue;
}
.btn:hover span {
top: -30px;
}
.btn:hover::after {
top: 5px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" rel="stylesheet"/>
<a href="#" class="btn">
<span>Add to cart</span>
</a>
Here is a slightly simpler example using two different p tags instead of text/svg. It shouldn't be too much trouble to convert:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
button {
width: 100px;
height: 40px;
overflow: hidden;
border: unset;
border-radius: 10px;
background-color: turquoise;
transition: all 200ms;
}
button:hover {
background-color: blue;
}
div {
height: 80px;
transform: translateY(0%);
transition: inherit;
}
div:hover {
transform: translateY(-50%)
}
p {
display: flex;
align-items: center;
justify-content: center;
color: white;
height: 50%;
font-size: 18px;
font-weight: 600;
}
<button>
<div>
<p class="one">text one</p>
<p class="two">text two</p>
</div>
</button>

Why does this link hover effect start from the middle and not the left?

I don't understand why in the code below, the link hover effect starts from the middle instead of going from left to right. Can someone please explain why this happens?
.orange-link {
color: orange;
position: relative;
text-decoration: none;
}
.orange-link:before {
content: "";
position: absolute;
width: 100%;
height: 3px;
background: orange;
bottom: 0;
border-radius: 5px;
transform: scaleX(0);
transition: .25s linear;
}
.orange-link:hover:before,
.orange-link:focus:before {
transform: scaleX(1);
}
<p>Visit the official rules <a class="orange-link" href="#">here</a> on how to send in a write-in entry.</p>
It's because the default origin of CSS transforms is the center of the element.
"By default it is at the center of the element and can be moved. It is used by several transforms, like rotations, scaling or skewing, that need a specific point as a parameter."
— https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transforms/Using_CSS_transforms
The line spans the full width, but is scaled to 0 (from the center) to start. Then, on hover, the line is scaled back up to it's original full width.
You need to change the transform-origin so that it starts from the left:
.orange-link {
color: orange;
position: relative;
text-decoration: none;
}
.orange-link:before {
content: "";
position: absolute;
width: 100%;
height: 3px;
background: orange;
bottom: 0;
border-radius: 5px;
transform: scaleX(0);
transition: .25s linear;
transform-origin:left bottom;
}
.orange-link:hover:before,
.orange-link:focus:before {
transform: scaleX(1);
}
<p class="read-or-listen-to-excerpt">
Visit the official rules <a class="orange-link" href="#">here</a> on how to send in a write-in entry.
</p>
You need to add transform-origin: top left; to .orange-link:before
Fiddle
Unless you specify the transform-origin, it will default to the center.
It is happening because you are scaling the element. It scales from the middle because the origin is in the middle (by default). As seen here
By default, the origin of a transform is "50% 50%", which is exactly in the center of any given element.
The possible fix can be to use the width
.orange-link {
color: orange;
position: relative;
text-decoration: none;
}
.orange-link::before {
content: "";
position: absolute;
width: 100%;
height: 3px;
left: 0 !important;
background: orange;
bottom: 0;
width: 0%;
border-radius: 5px;
transition: 0.25s linear;
}
.orange-link:hover::before,
.orange-link:focus::before {
width: 100%;
}
.orange-link {
color: orange;
position: relative;
text-decoration: none;
}
.orange-link::before {
content: "";
position: absolute;
width: 100%;
height: 3px;
left: 0 !important;
background: orange;
bottom: 0;
width: 0%;
border-radius: 5px;
transition: 0.25s linear;
}
.orange-link:hover::before,
.orange-link:focus::before {
width: 100%;
}
<p class="read-or-listen-to-excerpt">
Visit the official rules <a class="orange-link" href="#">here</a> on how to send in a write-in entry.
</p>
Or you can even shift the origin by transform-origin: bottom left; and do this
.orange-link {
color: orange;
position: relative;
text-decoration: none;
}
.orange-link:before {
content: "";
position: absolute;
width: 100%;
height: 3px;
background: orange;
bottom: 0;
transform-origin: bottom left;
border-radius: 5px;
transform: scaleX(0);
transition: .25s linear;
}
.orange-link:hover:before,
.orange-link:focus:before {
transform: scaleX(1);
}
<p class="read-or-listen-to-excerpt">
Visit the official rules <a class="orange-link" href="#">here</a> on how to send in a write-in entry.
</p>

CSS Only Multiple onclick events

This is generally a hack which i am trying to figure out in css, From what I can gather it should be working in theory and it isn't.
#expand {
width: 30px;
height: 30px;
background-color: rgba(0, 0, 0, 0);
}
#btn {
display: none;
}
#btn:checked+label:before {
transform: rotate(90deg);
}
#btn:checked+label:after {
transform: rotate(180deg);
}
#btn:checked+.button:before {
display: none;
}
#btn:checked+.button:after {
display: inline-block;
}
.button {
position: relative;
width: 25px;
height: 25px;
display: inline-block;
}
.button:before,
.button:after {
content: "";
position: absolute;
background-color: black;
transition: transform 0.35s ease-out;
}
/* Vert Line */
.button:before {
top: 0;
left: 46%;
width: 4px;
height: 100%;
margin-left: 2px;
margin-top: 2px;
}
/* Horiz Line */
.button:after {
top: 50%;
left: 0;
width: 100%;
height: 4px;
margin-left: 2px;
}
.inform {
display: none;
}
<div id="expand">
<input id="btn" type="checkbox">
<label class="button" for="btn"></label>
<div class="inform">
<h3>Heading</h3>
<p>Alot of content.</p>
</div>
So as you can see, I have the "hack" for the click event on changing the style for .button using a checkbox.
I then used the + selector to target the div .inform.
If i am correct the + selector means it targets the immediate following element, In which case this should work. But it does not, Could someone possibly help clear my understanding of this and if i am wrong, otherwise could you help point me in the right direction to get this to work.
Summary:
I would like to get the header and paragraph to display when the checkbox is checked, aswell as getting the + symbol to rotate.
You've got similar selectors:
#btn:checked+.button:before {
display: none;
}
#btn:checked+.button:before {
display: inline-block;
}
And #btn:checked+label:before and #btn:checked+.button:before are the same thing.
I think it should look like:
#expand {
width: 30px;
height: 30px;
background-color: rgba(0, 0, 0, 0);
}
#btn {
display: none;
}
#btn:checked+label:before {
transform: rotate(90deg);
}
#btn:checked+label:after {
transform: rotate(180deg);
}
#btn:checked+.button:before {
display: none;
}
#btn:checked ~ .inform {
opacity: 1;
}
.button {
position: relative;
width: 25px;
height: 25px;
display: inline-block;
}
.button:before,
.button:after {
content: "";
position: absolute;
background-color: black;
transition: transform 0.35s ease-out;
}
/* Vert Line */
.button:before {
top: 0;
left: 46%;
width: 4px;
height: 100%;
margin-left: 2px;
margin-top: 2px;
}
/* Horiz Line */
.button:after {
top: 50%;
left: 0;
width: 100%;
height: 4px;
margin-left: 2px;
}
.inform {
display: inline-block;
opacity: 0;
transition: all .5s ease;
}
<div id="expand">
<input id="btn" type="checkbox">
<label class="button" for="btn"></label>
<div class="inform">
<h3>Heading</h3>
<p>Alot of content.</p>
</div>

Text is not rotating with button

I need help rotating text at the same time that the button rotates. For some reason the text is currently disappearing when I hover the mouse over the button. The text should not be disappearing; it should be rotating with the button I'm using Chrome for this project.
http://codepen.io/matosmtz/pen/oXBaQE
HTML
<body>
<div class = "container">
<section class="3d-button">
<h2>Animated Button</h2>
<p class="btn_perspective">
<button class="btn btn-3d btn-3da">Submit</button>
</p>
</section>
</div>
</body>
CSS
html, body {
font-size: 100%;
padding: 0;
margin: 0;
height: 100%;
border: 0;
}
body {
font-family: Lekton;
background: rgb(245,245,245);
}
a {
color: #888;
text-decoration: none;
}
.container {
padding: 0;
margin: 0;
height: 100%;
background: #fff;
position: relative;
}
.container > section {
margin: 0 auto;
padding: 6em 3em;
text-align: center;
}
h2 {
margin: 20px;
text-align: center;
text-transform:uppercase;
letter-spacing: 1px;
font-size: 2em;
}
.btn {
border:none;
position: relative;
background: rgb(245,245,245);
padding: 15px 40px;
display: inline-block;
text-transform: uppercase;
margin: 15px 30px;
color: inherit;
letter-spacing: 2px;
font-size: .9em;
outline: none;
-webkit-transition: all 0.4s;
transition: all 0.4s;
cursor: pointer;
}
.btn:after {
content: "";
position: absolute;
z-index: -1;
-webkit-transition: all 0.4s;
transition: all 0.4s;
}
.btn_perspective {
-webkit-perspective: 800px;
perspective: 800px;
display: inline-block;
}
.btn-3d {
display: block;
background: #5cbcf6;
color: white;
outline: 1px solid transparent;
transform-style: preserve-3d;
}
.btn-3d:active {
background: #55b7f3;
}
.btn-3da:after {
width: 100%;
height: 42%;
left: 0;
top: -40%;
background: #53a6d7;
transform-origin: 0% 100%;
transform: rotateX(90deg);
}
.btn-3da:hover {
transform: rotateX(-45deg);
}
Here's the updated codepen: http://codepen.io/anon/pen/KpaGYd
Added the following code to your button:
.btn-3da:after {
z-index:1;
}
.btn-3da:hover {
position:relative;
z-index:2;
}
You can take a look into this pure CSS3 solution (works in all major web browsers: DEMO):
/*ROTATE*/
.divRotate
{
-moz-transition : all 0.8s;
-webkit-transition : all 0.8s;
-o-transition : all 0.8s;
transition : all 0.8s;
}
.divRotate:hover
{
-moz-transform : rotate(360deg);
-webkit-transform : rotate(360deg);
-o-transform : rotate(360deg);
transform : rotate(360deg);
}
Add the div element to your HTML and refer the class = 'divRotate'.
Hope this may help. Best regards,