I have a series of buttons with dynamic rotations:
<button type="button" class="picker-opt" opt-index="1" style="transform: rotateX(84.64deg) translate3d(0px, 0px, 90px); transition-duration: 150ms;">1</button>
<button type="button" class="picker-opt" opt-index="2" style="transform: rotateX(63.48deg) translate3d(0px, 0px, 90px); transition-duration: 150ms;">2</button>
<button type="button" class="picker-opt" opt-index="3" style="transform: rotateX(42.32deg) translate3d(0px, 0px, 90px); transition-duration: 150ms;">3</button>
I want to change all their translateZ values, but adding this rule:
.picker-opt { translate3d(0px, 0px, 100px) !important; }
also cancels out their rotateX, which is unacceptable.
I've enabled the Chrome Experimental Web Platform to get the independent translate but it doesn't appear to include translate3d! How silly.
If you want them to be indpendent then put the various tranforms on different elements.
button {
transform: translate3d(0px, 0px, 90px);
transition-duration: 150ms;
}
button:hover {
transform: translate3d(10px, 0px, 100px);
}
<div style="transform: rotateX(84.64deg);">
<button type="button" opt-index="1">1</button>
</div>
<div style="transform: rotateX(63.48deg);">
<button type="button" opt-index="2">2</button>
</div>
<div style="transform: rotateX(42.32deg);">
<button type="button" opt-index="3">3</button>
</div>
You could also use custom css :
button {
--var1 : 0;
--var2 : 0;
--var3 : 90px;
}
button:hover {
--var3 : 100px
}
/* for demo purpose*/
html {height:100vh;display:flex;}
body {margin:auto;}
<button type="button" class="picker-opt" opt-index="1" style="transform: rotateX(84.64deg) translate3d(var(--var1),var(--var2),var(--var3)); transition-duration: 150ms;">1</button>
<button type="button" class="picker-opt" opt-index="2" style="transform: rotateX(63.48deg) translate3d(var(--var1),var(--var2),var(--var3)); transition-duration: 150ms;">2</button>
<button type="button" class="picker-opt" opt-index="3" style="transform: rotateX(42.32deg) translate3d(var(--var1),var(--var2),var(--var3)); transition-duration: 150ms;">3</button>
you can also set empty var with a defaut value :
var(--myVar, green)
html {
background: var(--myVar, green);/* green if --myVar is not set */
transition:0.15s
}
html:hover {
--myVar: red; /* --myVar is now set */
}
Related
it's been awhile. Anyway, having some trouble getting an absolutely positioned element to stay center while animating. What's more is I'm seeing the element "shift" after the animation is complete and I have no idea why. Closest issue I found was css animations moves element position but that didn't solve for this common use case.
Debugging the animation frames, we can see the following:
During animation
After animation
Yuck! Playing with positioning didn't work, but animation-fill-mode did something; however, I noticed translate has no effect on the positioned element during animation or when animation-fill-mode is set to forwards or both. Why? The side effect is when the animation completes the element's position will not be recalculated so no repaint.
Example:
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
and the CSS using animate.css to make life easy:
.alert {
min-width: 500px;
position: absolute;
top: 0;
left: 50%;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
/* animation-fill-mode: forwards; */
transform: translateX(-50%);
}
Demo: https://codepen.io/atomicpages/pen/yrymVY?editors=1100
Goals:
Center aligned
Element is at least 500px
Element doesn't move after animation frame completes
Your help is appreciated.
Use custom fadeInDown without animate.css because it is using transform: translate3d(0, -100%, 0) in fadeIndown
.alert {
width: 500px;
top: 0;
left: 50%;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
transform: translateX(-50%);
position:absolute;
}
#keyframes fadeInDown{
from{
opacity:0;
}
to{
opacity:1;
}
}
#-webkit-keyframes fadeInDown{
from{
opacity:0;
}
to{
opacity:1;
}
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
Try removing transform: translateX, after the animation, the element stays where it is, and change it to left: 0;
.alert {
min-width: 500px;
top: 0;
left: 0;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
}
The reason is that the built-in fadeInDown also use transform for its animation, hence resets/override your initial value, and restore it after, unless you use animation-fill-mode: forwards;, which will keep it 50% off the left edge all the time.
And do note, preset transform "values", like translateX doesn't persist when another "value" is added to the "property", all existing values gets overwritten.
Original CSS
#keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
For yours to work you need to override the built-in one, adding your translateX value to it, and it will behave.
And if you do, there is a prefixed #keyframes rule as well, which also need to be updated.
New CSS
#keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(-50%, -100%, 0);
transform: translate3d(-50%, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(-50%, 0, 0);
transform: translate3d(-50%, 0, 0);
}
}
As a side note:
With the provided setting it will always take full width and centering it would have no effect, unless you also gave it a max-width somewhere else.
I need code for this functionality.
By default, it should be like right headed arrow and when i click it should be down headed arrow.
Thanks,
Ram
You can do it by using javascript. If you don't know how to use javascript, refer to the code below.
<html>
<head>
<title>Title</title>
<script type="text/javascript>
function myFunction(){
document.getElementById('img').src = "down.jpg";
}
</script>
<body>
<img src="right.jpg" id="img" onclick="myFunction();"/>
</body>
</html>
Enjoy :D
As you can see, we fetch the element in js using its id and change its src attribute and set it to your another image. You can change the event which is onclick as per your needs. You can use ondblclick to trigger the function on double click. ^-^
This may help you #pbrc1995 :)
function myFunction(x) {
x.classList.toggle("change");
}
.container {
display: inline-block;
cursor: pointer;
}
.bar1, .bar2, .bar3 {
width: 35px;
height: 5px;
background-color: #333;
margin: 6px 0;
transition: 0.4s;
}
.change .bar1 {
-webkit-transform: rotate(-45deg) translate(-9px, 6px) ;
transform: rotate(-45deg) translate(-9px, 6px) ;
}
.change .bar2 {opacity: 0;}
.change .bar3 {
-webkit-transform: rotate(45deg) translate(-8px, -8px) ;
transform: rotate(45deg) translate(-8px, -8px) ;
}
<p>Click on the Menu Icon to transform it to "X":</p>
<div class="container" onclick="myFunction(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
Since you are not asking for a JavaScript solution, here's one without it.
div.arrow {
width:33px; height:30px;
background:url('https://i.stack.imgur.com/yMatp.png');
}
div.arrow:active{
width:51px; height:26px;
background:url('https://i.stack.imgur.com/M3Bew.png');
}
<div class="arrow"></div>
I am trying to create a hamburger menu button on a navbar inside a mobile web. This is my first time to build mobile web. And this code only show a huge square kind button instead of a nice hamburger menu. Please help.
<nav class="navbar-static-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand ui-link" onclick="window.location.href='/'"href</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#popup">
<span class="text">Menu</span>
<span class="icon-bars">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</span>
</button>
</div>
</div>
</nav>
I'm not quite sure what you're trying to accomplish, but one thing you are missing in your "hamburger menu" is a color for the "bars".
So if you just add for example a background-color to your icon-bar elements it will show the hamburger menu.
.icon-bar {
background-color: black;
}
JSFiddle
You can just embed this code where you want a hamburger menu and it will automatically display the menu:
<svg>
<path fill="black" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path>
</svg>
div {
width: 35px;
height: 5px;
background-color: black;
margin: 6px 0;
}
<p>A humburger icon:</p>
<div></div>
<div></div>
<div></div>
The problem in your code is that you used a span instead of a div, which has made all the difference, because span is an inline element and div is a block level element.
Using divs with some CSS as mentioned in this answer can help, but there are many ways through it.
You can use SVG, if you want a simple icon. It has been mentioned in this answer, but I'll still quote it:
<svg>
<path fill="black" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path>
</svg>
You can also create an animated icon, like this:
function myFunction(x) {
x.classList.toggle("change");
}
.container {
display: inline-block;
cursor: pointer;
}
.bar1, .bar2, .bar3 {
width: 35px;
height: 5px;
background-color: #333;
margin: 6px 0;
transition: 0.4s;
}
/* Rotate first bar */
.change .bar1 {
-webkit-transform: rotate(-45deg) translate(-9px, 6px) ;
transform: rotate(-45deg) translate(-9px, 6px) ;
}
/* Fade out the second bar */
.change .bar2 {
opacity: 0;
}
/* Rotate last bar */
.change .bar3 {
-webkit-transform: rotate(45deg) translate(-8px, -8px) ;
transform: rotate(45deg) translate(-8px, -8px) ;
}
<div class="container" onclick="myFunction(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
Hope I could help
I am attempting to animate the horizontal lines in the navbar to an 'X' when the page is reduced in size.
My navbar code is as follows:
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">Company</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
About<b class="caret"></b>
<ul class="dropdown-menu">
<li>
About Us
</li>
<li>
Certification
</li>
<li>
Download PDF
</li>
</ul>
</li>
<li>
Products
</li>
<li>
Inquiry
</li>
<li>
Events
</li>
<li>
Contact
</li>
<li>
Login
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
When I attempt to use the CSS shown here it does not work. Is there something I need to modify for my navbar specifically? I also notice that when I add the css, the :
&:hover {
background: transparent !important;
}
the closing curly brace does not recognize the opening one. What am i missing?
It's because the tutorial is using Less, a CSS pre-processor, extending the CSS language.
However, you just have to use the compiled CSS, and make a few changes.
In your html, add some classes to the bars in order to distinguish each of them :
<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>
Also, init your button with the class collapsed, or it will first render as a 'X'.
Then add the CSS compiled :
.navbar-toggle {
border: none;
background: transparent !important;
}
.navbar-toggle:hover {
background: transparent !important;
}
.navbar-toggle .icon-bar {
width: 22px;
transition: all 0.2s;
}
.navbar-toggle .top-bar {
transform: rotate(45deg);
transform-origin: 10% 10%;
}
.navbar-toggle .middle-bar {
opacity: 0;
}
.navbar-toggle .bottom-bar {
transform: rotate(-45deg);
transform-origin: 10% 90%;
}
.navbar-toggle.collapsed .top-bar {
transform: rotate(0);
}
.navbar-toggle.collapsed .middle-bar {
opacity: 1;
}
.navbar-toggle.collapsed .bottom-bar {
transform: rotate(0);
}
And now it should work like a charm.
Here's a JsFiddle : Demo
This worked for me
Theory
CSS provides all the necessary animation tools. Basically what's happening is this:
The top and bottom lines must rotate to form the X
The middle line must disappear
The X will be taller an more narrow than the hamburger lines, so:
The top and middle lines must move out vertically and to the right to maintain its center
Application
/* Define the shape and color of the hamburger lines */
.navbar-toggler span {
display: block;
background-color: #4f4f4f;
height: 3px;
width: 25px;
margin-top: 5px;
margin-bottom: 5px;
position: relative;
left: 0;
opacity: 1;
transition: all 0.35s ease-out;
transform-origin: center left;
}
/* top line needs a little padding */
.navbar-toggler span:nth-child(1) {
margin-top: 0.3em;
}
/**
* Animate collapse into X.
*/
/* top line rotates 45 degrees clockwise and moves up and in a bit to close the center of the X in the center of the button */
.navbar-toggler:not(.collapsed) span:nth-child(1) {
transform: translate(15%, -33%) rotate(45deg);
}
/* center line goes transparent */
.navbar-toggler:not(.collapsed) span:nth-child(2) {
opacity: 0;
}
/* bottom line rotates 45 degrees counter clockwise, in, and down a bit to close the center of the X in the center of the button */
.navbar-toggler:not(.collapsed) span:nth-child(3) {
transform: translate(15%, 33%) rotate(-45deg) ;
}
/**
* Animate collapse open into hamburger menu
*/
/* top line moves back to initial position and rotates back to 0 degrees */
.navbar-toggler span:nth-child(1) {
transform: translate(0%, 0%) rotate(0deg) ;
}
/* middle line goes back to regular color and opacity */
.navbar-toggler span:nth-child(2) {
opacity: 1;
}
/* bottom line goes back to initial position and rotates back to 0 degrees */
.navbar-toggler span:nth-child(3) {
transform: translate(0%, 0%) rotate(0deg) ;
}
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<!-- Bootstrap Navigation -->
<nav class="navbar bg-light">
<a class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar">
<span> </span>
<span> </span>
<span> </span>
</a>
<a class="navbar-brand" href="./">
Brand
</a>
<div class="collapse navbar-collapse" id="collapsingNavbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</nav>
<main class="container">
<h1>Content Here</h1>
<p>Shrink the viewport if to expose the hamburger menu.</p>
</main>
What makes it work
Specifically, since the top and bottom lines rotate by 45 degrees to form the X, their center lines take up 70% of the width, so they must move in by 15%. This can be calculated using pythagorean theorem.
As it happens, our hamburger menu is 26x21 px, or 24% wider than it is tall, but the X ends up being 20x20 square when you move the lines into place and you take into account the height of the lines (here defined as 3px).
In this particular implementation, we are defining the point of rotation of each line as being the center-left. This affects how much we move the lines up, since the lines are about 3px tall, they each add about (2.1/2)=1.05px to the height of the X, or about 33% of the height of the X.
Therefore 33% is how much they must move out vertically out so the two lines meet at the center of the X and form a 20x20px square.
Customizing
The X will always make a square, so to find out how much to move them by, you just need to know the width and height of your <span> bars and the height of the resulting hamburger icon.
Plug those numbers into this equation:
Or in code:
const line_width = 26; // px
const line_height = 3; // px
const hamburger_height = 21; // px
const x_width = x_height = 0.8 * line_width;
const line_move_y_percent = 100 * (line_width - x_width) / (2 * line_height)
const line_move_right_percent = 100 * (x_height - hamburger_height) / (2 * line_height)
I managed to adopt Adonis' excellent answer (go and upvote) to work on one of Bootstrap 5's navbar examples with some notable changes:
With Bootstrap 5's existing navbar-toggler-icon span, there only needs to be two extra spans for the icon bars, not three
The button needs to have the collapsed class in order to avoid initialising as an X instead of the menu
Made the animation a bit faster
With those changes in mind, here is the reflected markup for an animated hamburger menu animation in Bootstrap 5:
<nav class="navbar navbar-expand-lg navbar-light bg-light collapsed" aria-label="Eighth navbar example">
<div class="container">
<a class="navbar-brand me-6 me-xl-7" href="#">Brand</a>
<button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target="navbarsExample07" aria-controls="navbarsExample07" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
<span></span>
<span></span>
</button>
<div class="collapse navbar-collapse" id="navbar-home">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
<a class="nav-link" href="#">Find My Car</a>
</li>
<li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
<a class="nav-link" href="#">Frequently Asked Questions</a>
</li>
<li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
<a class="nav-link" href="#">Testimonials</a>
</li>
<li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
<a class="nav-link" href="#">Contact Us</a>
</li>
</ul>
</div>
</div>
</nav>
And the CSS:
.navbar-toggler span {
display: block;
background-color: #000;
height: 3px;
width: 25px;
margin-top: 5px;
margin-bottom: 5px;
position: relative;
left: 0;
opacity: 1;
transition: all 0.2s ease-out;
transform-origin: center left;
}
.navbar-toggler span:nth-child(1) {
margin-top: 0.3em;
}
.navbar-toggler:not(.collapsed) span:nth-child(1) {
transform: translate(15%, -33%) rotate(45deg);
}
.navbar-toggler:not(.collapsed) span:nth-child(2) {
opacity: 0;
}
.navbar-toggler:not(.collapsed) span:nth-child(3) {
transform: translate(15%, 33%) rotate(-45deg) ;
}
.navbar-toggler span:nth-child(1) {
transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggler span:nth-child(2) {
opacity: 1;
}
.navbar-toggler span:nth-child(3) {
transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggle .icon-bar {
width: 26px;
height: 2px;
transition: all 0.2s;
}
This should do it, if not just try to adjust the width value in the range of 20px-26px.
Based on the answers above, my adaptation for Bootstrap 5.1. Working with booth
collapse & offcanvas. I used jQuery, but is not required.
Button:
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar" aria-controls="offcanvasNavbar">
<span></span><span></span><span></span>
</button>
JavaScript:
let $btn = $('.navbar-toggler');
$($btn.data('bs-target')).on('show.bs.collapse hide.bs.collapse show.bs.offcanvas hide.bs.offcanvas', function(){
$btn.toggleClass('opened');
});
Css:
.navbar-toggler {
border: 0;
box-shadow: none;
}
.navbar-toggler:focus {
box-shadow: none;
}
.navbar-toggler span {
display: block;
background-color: #4f4f4f;
height: 3px;
width: 25px;
margin-top: 5px;
margin-bottom: 5px;
position: relative;
left: 0;
opacity: 1;
transition: all 0.2s ease-out;
transform-origin: left center;
}
.navbar-toggler span:nth-child(1) {
margin-top: 0.3em;
}
.navbar-toggler:not(.opened) span:nth-child(1){
transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggler:not(.opened) span:nth-child(2) {
opacity: 1;
}
.navbar-toggler:not(.opened) span:nth-child(3) {
transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggler span:nth-child(1) {
transform: translate(15%, -33%) rotate(45deg);
}
.navbar-toggler span:nth-child(2) {
opacity: 0;
}
.navbar-toggler span:nth-child(3) {
transform: translate(15%, 33%) rotate(-45deg) ;
}
I'm trying to make a html page with a cube on it, each face of said cube would have buttons on it. On the default face all the buttons work fine, however, as soon as I rotate the cube the new face looses all interactivity.
HTML:
<button type="button" id="button">Toggle</button>
<hr>
<div id="cube">
<div class="face one"></div>
<div class="face two">
<button type="button">All</button>
<button type="button">News</button>
<button type="button">Media</button>
<button type="button">Events</button>
</div>
<div class="face three"></div>
<div class="face four"></div>
<div class="face five">
<button type="button">All</button>
<button type="button">News</button>
<button type="button">Media</button>
<button type="button">Events</button>
</div>
<div class="face six"></div>
</div>
CSS:
#cube {
position: relative;
height: 400px;
-webkit-transition: -webkit-transform 2s linear;
-webkit-transform-style: preserve-3d;
}
.face {
position: absolute;
height: 360px;
background-color:#ffffff;
}
#cube .one {
-webkit-transform: rotateX(90deg) translateZ(200px);
}
#cube .two {
-webkit-transform: translateZ(200px);
}
#cube .three {
-webkit-transform: rotateY(90deg) translateZ(200px);
}
#cube .four {
-webkit-transform: rotateY(180deg) translateZ(200px);
}
#cube .five {
-webkit-transform: rotateY(-90deg) translateZ(200px);
}
#cube .six {
-webkit-transform: rotateX(-90deg) translateZ(200px) rotate(180deg);
}
And JS:
$("#button").click(function () {
$('#cube').css("-webkit-transform", "rotateX(0deg) rotateY(90deg)");
});
Here's a Fiddle link demonstrating my problem: http://jsfiddle.net/x66yn/
(Note that the demo will only work on webkit browsers.)
You need to give the elements a non-static position. This is because the elements are not currently positioned in their parent, with the parent being moved forward it covers the children
button {
position: relative; /* Or absolute, fixed */
}
Demo
Note: I added a cursor change on hover to show it works
The other option is to move the buttons forward in the Z direction greater than or equal to it's parent z-axis movement since you're doing so with the parent
button {
-webkit-transform: translateZ(200px); /* Equivalent or greater than parent's*/
transform: translateZ(200px);
}
Demo
In your case specifically, the back panel will not work just using the above, the angle of the right button also cannot be 90 (some some reason which I don't know for sure). It has to do with how the browser is rendering it. As a result, just use 89.999 which is indistinguishable to us but works fine
$("#buttonRight").click(function () {
$('#cube').css("-webkit-transform", "rotateX(0deg) rotateY(89.999deg)");
});
I had similar problem, but for me help remove from cube(DIV) this ruls: backface-visibility : hidden; and rotate cube by 89.99 (just two "9" after dot)
With this cube work in Chrome, Firefox, Safari and IE11