I am trying to create an animation effect that moves two buttons when I click on them. I have the flex direction set up as a column in the container div and I essentially just want them to position as a flex row when I click on one of them (probably with a 1s animation). When I click on them currently nothing happens. Here is my code sample:
HTML
<header>
<div class="container">
<h1>Choose Your Allegiance</h1>
<div id="buttons">
<button class="fill"><img src="/assets/Jedi.png" alt="Jedi" /></button>
<button class="fill sith">
<img src="/assets/Sith.png" alt="Sith" />
</div>
</button>
</div>
</header>
CSS
.container {
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
}
.container.click {
flex-direction: row;
justify-content: space-around;
}
h1 {
margin-left: 5vw;
color: black;
font-family: "Poller One", cursive;
font-variant: small-caps;
font-size: 3rem;
margin-top: 6vh;
}
button {
color: white;
transition: 0.25s;
float: left;
margin: 2%;
}
button:hover,
button:focus {
border: 2px solid red;
color: black;
}
.fill {
height: 120px;
width: 150px;
background: transparent;
margin-top: 4vh;
outline: none;
border: none;
}
.fill:hover,
.fill:focus {
box-shadow: inset 0 0 0 4.5em #add8e6;
}
.sith:hover,
.sith:focus {
box-shadow: inset 0 0 0 4.5em black;
}
#buttons {
height: 100%;
width: 100vw;
padding-top: 10vh;
display: flex;
justify-content: center;
}
JS
document.querySelector("button").addEventListener("click", () => {
document.querySelector(".container").classList.toggle(".container.click");
});
There are a couple of changes you need to make to get this to work:
1. document.querySelector("button") is only selecting the first button. There are 2 you can add an event listener to the buttons
use document.querySelectorAll("button") to get all the buttons, and then you can loop through them adding an event Listener to each one:
document.querySelectorAll("button").forEach(function(button) {
button.addEventListener("click", () => {
document.querySelector(".container").classList.toggle("click");
});
});
A better way is to add an event listener to the buttons container - you can get the element using getElementById and then add the listener to it:
var buttons = document.getElementById("buttons");
buttons.addEventListener("click", (e) => {
document.querySelector(".container").classList.toggle("click");
});
2. You just use the class name when passing a class into toggle- you don't need the .. Also, you only need to toggle the click class as the container class will always apply. So what you need to use is .toggle("click");
Working Example (without your images):
var buttons = document.getElementById("buttons");
buttons.addEventListener("click", (e) => {
document.querySelector(".container").classList.toggle("click");
});
.container {
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
}
.container.click {
flex-direction: row;
justify-content: space-around;
}
h1 {
margin-left: 5vw;
color: black;
font-family: "Poller One", cursive;
font-variant: small-caps;
font-size: 3rem;
margin-top: 6vh;
}
button {
color: red;
transition: 0.25s;
float: left;
margin: 2%;
}
button:hover,
button:focus {
border: 2px solid red;
color: black;
}
.fill {
height: 120px;
width: 150px;
background: transparent;
margin-top: 4vh;
outline: none;
border: none;
}
.fill:hover,
.fill:focus {
box-shadow: inset 0 0 0 4.5em #add8e6;
}
.sith:hover,
.sith:focus {
box-shadow: inset 0 0 0 4.5em black;
}
#buttons {
height: 100%;
width: 100vw;
padding-top: 10vh;
display: flex;
justify-content: center;
}
<header>
<div class="container">
<h1>Choose Your Allegiance</h1>
<div id="buttons">
<button class="fill">Jedi</button>
<button class="fill sith">Sith</button>
</div>
</div>
</header>
As for animating this change, unfortunately CSS animations cannot be applied to flexbox direction property.
You are using classList.toggle wrong. You'll need to do this instead:
const container = document.querySelector(".container");
container.classList.toggle("click");
Documentation on Element.classList here.
Related
I have two html buttons that show different information when clicked. I am using jQuery to change which button has the default button CSS and the active button CSS. My code is below. Currently, when I click the opposite button, the default active button does not switch to inactive styles. Any suggestions? Thanks in advance!
HTML:
<div class="center-buttons container space-between btn-group">
<button type="button" id="xValues" class="mobile-buttons desktop-w active-2">Button 1</button>
<button type="button" id="yValues" class="mobile-buttons desktop-w">Button 2</button></div>
jQuery:
$('.btn-group').on('click', 'button', function(){
$('.btn-group button.active-2').removeClass('active-2');
$(this).addClass('active-2');
CSS:
.center-buttons {
text-align: center;
margin: 20px 0px;
}
.container {
display: flex;
}
.space-between {
justify-content: space-between;
}
.mobile-buttons {
margin: 5px;
border: none;
border-bottom: 3px solid #B0B0B0;
color: #B0B0B0;
font-weight: 700;
font-size: 12px;
}
.active-2, .mobile-buttons:hover {
background-color: #fff;
border-bottom: 3px solid #2d2d2d;
color: #2d2d2d;
}
.desktop-w {
width: 49%;
}
There seems to be a syntax error in the jQuery code. The application runs when the event handler method is terminated with "})".
/* The event handler method is not terminated with "})". */
$('.btn-group').on('click', 'button', function(){
$('.btn-group button.active-2').removeClass('active-2');
$(this).addClass('active-2');
});
.center-buttons {
text-align: center;
margin: 20px 0px;
}
.container {
display: flex;
}
.space-between {
justify-content: space-between;
}
.mobile-buttons {
margin: 5px;
border: none;
border-bottom: 3px solid #B0B0B0;
color: #B0B0B0;
font-weight: 700;
font-size: 12px;
}
.active-2, .mobile-buttons:hover {
background-color: #fff;
border-bottom: 3px solid #2d2d2d;
color: #2d2d2d;
}
.desktop-w {
width: 49%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="center-buttons container space-between btn-group">
<button type="button" id="xValues" class="mobile-buttons desktop-w active-2">Button 1</button>
<button type="button" id="yValues" class="mobile-buttons desktop-w">Button 2</button></div>
This question already has answers here:
How do I detect a click outside an element?
(91 answers)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
My current code opens up an input via a click by adding a class. I'm having trouble adding a second click that removes the added class when the user clicks off the input. I added a second click event but it just stops my first click event from working.
Is there a different way to approach this using pure JavaScript?
(Commented out failed attempt.)
let searchElement = document.querySelector('#searchElement');
let offCanvas = document.querySelector('#main');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
// offCanvas.addEventListener('click', () => {
// searchElement.classList.remove('extendInputSearch');
// });
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
The problem with your attempt is that the event listener to remove the class is applied to the entire #main element, which includes searchElement. That means both event listeners are applied to the searchElement, and when you click on the searchElement, the class is first added (with the first listener) and then removed (with the second listener).
To make it work, you need to change the second listener to specifically exclude the searchElement. For example, in this code, we add a click listener to the whole document. In the listener, we check if the click is outside the searchElement by using the Node.contains() function on the event parameter. If the clicked element is not a child of searchElement (that is, the click is outside searchElement), we remove the extendInputSearch class from searchElement.
let searchElement = document.querySelector('#searchElement');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
document.addEventListener('click', (e) => {
if(!searchElement.contains(e.target)){
searchElement.classList.remove('extendInputSearch');
}
});
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
try it:
let searchElement = document.querySelector('#searchElement');
let offCanvas = document.querySelector('#main');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
document.addEventListener('click', (e) => {
const searchElement = document.querySelector('#searchElement');
if (e.target != searchElement && e.target != searchElement.querySelector('i') && e.target != searchElement.querySelector('input')) {
searchElement.classList.remove('extendInputSearch');
}
});
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
I want to create two button which will float next to each other and also when we click one of them it will change background-color to #474e5d and some shadow effect. I am very new to design please help me to do this.
Click here to see the button design
//js
const span2 = document.getElementById("span2")
const span1 = document.getElementById("span1")
span2.addEventListener("click",function ( ) {
const span3 = document.getElementById("span3")
span3.style.left="150px"
span3.innerHTML="Search by dictric"
span3.style.transition = "all 0.5s";
})
span1.addEventListener("click",function () {
const span3 = document.getElementById("span3")
span3.style.left="0px"
span3.innerHTML="Search by pin code"
span3.style.transition = "all 0.5s";
})
/* css */
.sld_btn{
display: flex;
width: 300px;
height: 40px;
border-radius: 25px;
position: relative;
background-color: rgb(102, 102, 102);
}
.sld_btn span{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all 0.5;
}
#span3{
border-radius: 25px;
position: absolute;
height: 100%;
width:150px ;
background-color: rgb(151, 151, 151);
box-shadow: 5px 5px 5px rgba(41, 41, 41, 0.5);
}
<!-- HTML -->
<div class="sld_btn">
<span class="span1" id="span1">Search by pin code</span>
<span id="span2">Search by dictric</span>
<span class="span3" id="span3">Search by pin code</span>
</div>
I think this is close to what you are looking for. I can explain individual parts if you want.
Click on Run Code Snippet to see it working.
const buttons = document.querySelectorAll('.button');
function onButtonClick(event) {
for (button of buttons) button.classList.remove('clickedButton');
event.target.classList.add('clickedButton');
}
.container {
display: flex;
border-radius: 32px;
background-color: grey;
width: max-content;
}
.button {
cursor: pointer;
padding: 16px;
text-align: center;
border-radius: 32px;
font-size: 14px;
transition: all 0.25s ease;
}
.clickedButton {
background-color: #474e5d;
box-shadow: 0px 0px 15px #444;
color: white;
}
<div class="container">
<div class="button" onclick="onButtonClick(event)">Search by Pin Code</div>
<div class="button" onclick="onButtonClick(event)">Search by District</div>
</div>
I currently am trying to code a website to animate moving across the x-axis to access different sections of the page (page content in 'tab-content'). I have a navbar that has different headers, this is fixed, I want the user to click on each header and be taken to that section. I managed to take the user to the desired section/div with some JS code however, there isn't any animation it defaults to the selected section/div just suddenly being on screen. How do I animate with pure JS or CSS. I need the clicking of the header to move (motion) the user to that div. I'm new to web dev.
here some of my code
HTML
<div class="main-info">
<div class="nav-container">
<div class="nav-bar">
<ul>
<li data-tab-target="#show" class="tab">Show</li>
<li data-tab-target="#about" class="tab">About</li>
<li data-tab-target="#lookbook" class="tab">Lookbook</li>
<li data-tab-target="#process" class="tab">Process</li>
</ul>
</div>
<div class="info overlay">
<div class="text">
MA
Coming Soon
BA
</div>
Back
</div>
</div>
<div class="tab-content">
<div id="show" data-tab-content class="active">
<p>VIDEO</p>
</div>
<div id="about" data-tab-content>
<p>About</p>
</div>
<div id="lookbook" data-tab-content>
<p>Lookbook</p>
</div>
<div id="process" data-tab-content>
<p>Process</p>
</div>
</div>
</div>
CSS
.main-info {
background-color: transparent;
height: 100vh;
overflow: hidden;
}
.nav-container {
position: fixed;
}
.nav-bar {
width: 80vw;
height: 10vh;
left: 10vw;
position: absolute;
top: 5vh;
}
.nav-bar ul {
text-transform: uppercase;
list-style: none;
margin: 0;
padding: 0;
display: flex;
justify-content: space-around;
}
.tab a {
font-family: Helvetica, sans-serif;
font-weight: bold;
font-size: 1rem;
color: black;
text-decoration: none;
}
.tab:hover {
cursor: pointer;
opacity: 0.6;
}
.tab.active {
background-color: whitesmoke;
}
.info {
width: 90vw;
height: 10vh;
/* border: 1px solid red; */
left: 5vw;
position: absolute;
top: 80vh;
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.info a {
font-family: Helvetica, sans-serif;
font-weight: bold;
font-size: 1.1rem;
color: black;
text-decoration: none;
border: 1px solid teal;
}
.text {
width: 30%;
display: flex;
justify-content: space-between;
}
.tab-content {
border: 1px solid teal;
position: absolute;
left: 0;
top: 0;
height: 100vh;
z-index: -11;
display: flex;
flex: row nowrap;
justify-content: flex-start;
}
[data-tab-content] {
border: 1px solid blueviolet;
background-color: violet;
font-size: 3rem;
color: blue;
scroll-behavior: smooth;
display: none;
width: 100vw;
height: 100vh;
}
.active[data-tab-content] {
display: block;
}
JS
const tabs = document.querySelectorAll('[data-tab-target]');
const tabContents = document.querySelectorAll('[data-tab-content]')
// loop through the list to find the one tab mouse clicked
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = document.querySelector(tab.dataset.tabTarget)
tabContents.forEach(tabContent => {
tabContent.classList.remove('active')
})
tabs.forEach(tab => {
tab.classList.remove('active')
});
tab.classList.add('active')
target.classList.add('active');
});
});
You almost got it. Instead of setting the scroll-behavior on the elements that are inside a scrollable element, put it on either the element that has a scrollbar.
.tab-content {
scroll-behavior: smooth;
}
Or on the top most element to have all elements move with a smooth scrolling animation.
:root {
scroll-behavior: smooth;
}
I have the following HTML:
<div class="admonition info">
<p class="admonition-title">Info</p>
<p>Text here</p>
</div>
And CSS:
.admonition {
border: 1px solid red;
display: flex;
justify-content: center;
align-items: center;
}
.admonition > p {
margin: 0;
padding: 6px;
display: block;
}
.admonition-title {
background-color: #2B83BD;
color: #fff;
display: block;
padding: 2px;
}
.admonition > .admonition-title {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
width: 64px;
text-align: center;
vertical-align: middle;
min-width: 60px;
}
.admonition > .admonition-title:before {
font-family: "FontAwesome";
font-size: 32px;
letter-spacing: normal;
color: #fff;
}
.admonition.info > .admonition-title:before {
content: "\f129";
}
.admonition.info > p:not(.admonition-title) {
background-color: #7DBAE3;
}
.admonition.info > .admonition-title {
background-color: #2B83BD;
}
I would like to render the children with the following constraints:
They are vertically centered
If their height is not equal, they should stretch to fill the gaps
The white gaps are what I would like to avoid. Live on JSFiddle
The HTML is generated from markdown and I don't really have control over the structure. Is this possible to implement in a simple way? Javascript, jquery is also OK, but I'd prefer to do this in CSS.
Just use align-items: stretch; to make the items fill the parent height.
Then, your icon will need to be centered manually, I have done it with:
.admonition > .admonition-title {
display: flex;
align-items: center;
justify-content: center;
}
https://jsfiddle.net/4mw8a08x/