flexbox is misbehaving with javascript active class - javascript

Navbar
Beginner here
As you can see everything is working perfectly until you click on the space between the links you can check here- my codepen. when I click on the links navbar it perfectly shows the active class, but if I click in between the space the whole navbar loses the class.
var element = document.getElementsByClassName("flex-nav")[0];
element.addEventListener("click", myFunction);
function myFunction(e) {
var elems = document.querySelector(".active");
if(elems !==null) {
elems.classList.remove("active");
}
e.target.className = "active";
}
.flex-nav {
display: flex;
flex-direction: column;
margin-top: 54px;
background: #333;
width: 75px;
height: 657px;
justify-content: space-around;
align-items: stretch;
line-height: 23px;
}
.flex-nav a{
text-decoration: none;
color: white;
flex-wrap: wrap;
text-align: center;
margin: 5px;
border: 1px solid transparent;
}
.flex-nav a.active {
background: #9999ff;
}
.flex-nav a:hover:not(.active) {
background: #555;
border: 1px solid rgba(255, 51, 153,1);
}
<div class="flex-nav">
2k
4k
1080p
8k
</div>

You can avoid that behaviour by letting the flex items grow so that there is no space between them: Add these settings to .flex-nav a
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
(The first is for the growing, the others are for centering the text inside them)

Related

How to create multiple row with two columns in React app

Well, in my react app, I want multiple rows having two columns. Just like first pink picture below.
But I am getting it like this. The divs are floating on the left side only, and nothing is working.
I think there should be a solution for using in map method. react component code.
{dog.map((data) => (
<div key={data.id} className="dogs-list">
<div id={data.id} className="first-column">
<img src={dogPic} alt="dog"></img>
<h3>Dog's Name</h3>
<h3>{data.name}</h3>
</div>
</div>
))}
Nothing is working. Can anyone please help?
this is the styling of this area.
.page .dogs-list {
/* display: flex; */
color: white;
width: 100%;
}
.page .dogs-list .first-column {
width: 50%;
/* border: 2px yellow solid; */
/* display: flex;
flex-direction: column; */
float: right;
}
.dogs-list img {
height: 250px;
width: 100%;
}
.dogs-list h3 {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 10px;
font-size: 18px;
}
Looking forward!
If you do not have a given structure to follow, (there was none mentioned?) try the following.
.dogs-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.dog{
width: calc(50% - 4px);
background-color: beige;
border: 2px yellow solid;
display: flex;
flex-direction: column;
}
.dogs-list img {
height: 250px;
width: 100%;
}
.dogs-list h3 {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 10px;
font-size: 18px;
}
<div className='dogs-list'>
{dog.map(data => (
<div id={data.id} className='dog'>
<img src={data.dogPic} alt='dog' />
<h3> Dog 's Name</h3> <h3> {data.name} </h3>
</div>
))}
</div>

Error in event handler: TypeError: Cannot read property 'dataset' of null

So i get this above mentioned error when i click my hamburger. And after clicking the hamburger my whole page turns white and when i right click nothing appears at all. Where is the issue here?I searched a lot of similar problems on the internet. Theres only talks about putting the script tag at the bottom and writing the window.onload function. I have put the script tag at the bottom of the body still this is happening.
ERROR MESSAGE:
Error in event handler: TypeError: Cannot read property 'dataset' of null
at Jr (chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:103527)
at Xr.updateState (chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:105004)
at chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:105819
at chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:73161
at chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:110691
at Array.forEach ()
at wi.fire (chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:110679)
at _onBgPortMessage (chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/src/js/Grammarly-check.js:2:115134)
HTML
<header>
<nav class="wrapper2">
<div class="logo">
<h1>LO</h1>
</div>
<div class="navbar">
<ul>
<li><a>ABOUT</a></li>
<li>ARTICLES</li>
<li>SUBSCRIBE</li>
</ul>
</div>
</nav>
<div class="hamburger" onclick="open()">
<span class="bar"></span>
<span class="bar"></span>
</div>
<div class="hero">
<h1>LOMBOK</h1>
<h2>HOLISTIC HEALTH & MORE</h2>
<div class="bigbar"></div>
</div>
</header>
SASS
header{
background-image: url(../images/heroimg.jpg);
background-size: cover;
background-position: 65%;
height: 100vh;
margin: 10px;
nav{
display: none;
justify-content:space-between;
.logo{
font-size: 1.5rem;
position: relative;
top: -10px;
}
.navbar ul{
display: flex;
width: 480px;
justify-content: space-between;
li{
list-style: none;
cursor: pointer;
letter-spacing: 0.2rem;
a{
text-decoration: none;
color: black;
}
}
li:last-child{
border: 2px solid black;
padding: 15px 20px;
position: relative;
top:-16px;
}
}
}
.hamburger{
position: absolute;
top: 2rem;
right: 1.8rem;
display: flex;
flex-direction: column;
justify-content: space-around;
width: 30px;
height: 20px;
cursor: pointer;
.bar{
height: 5px;
width: 100%;
background-color:$primary-color;
border-radius: 10px;
}
}
.hero{
height: 80vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
line-height: 1.7;
h1{
font-size: $primary-size;
font-weight: 600;
}
h2{
font-size: $secondary-size;
font-weight: 500;
}
.bigbar{
display: inline-block;
height: 7px;
width: 45px;
background-color: $secondary-color;
margin-top: 20px;
}
}
}
.active{
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.bgdark{
background-position: left bottom;
opacity: 0.4;
}
.inactive{
display: none;
}
JS
window.onload = function() {
const open = ()=> {
const nav = document.querySelector("nav");
const header=document.querySelector("header");
const hero=document.querySelector(".hero");
nav.classList.toggle(".active");
header.classList.toggle(".bgdark");
hero.classList.toggle(".inactive");
};
};
Ok so the issue here is that the open() function is a reserved method on the window object https://developer.mozilla.org/en-US/docs/Web/API/Window/open
So when you add open() on the onclick argument it will fire the window.open() method, which whenever executed without any arguments just opens a black page (hence no DOM to be inspected)
So one of the easy fixes is just to rename the function to anything that is not already a standard method of the window object. Or just add an anonymous function as a callback to the click event in the js file
document.querySelector('.hamburger').addEventListener('click', function(e) {
const nav = document.querySelector("nav");
const header=document.querySelector("header");
const hero=document.querySelector(".hero");
nav.classList.toggle("active");
header.classList.toggle("bgdark");
hero.classList.toggle("inactive");
});
and here's some simple fiddle
https://jsfiddle.net/5hdk1op4/

Change the flex-direction on button click

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.

How to have a tab containing flexible height menu fixed at bottom of window and slide up on click using jQuery?

I tried coding it myself based on research on the internet. I was able to get it fixed at the bottom. When clicking, it does slide out the menu; but it slides out downwards when it should have pushed the tab upwards to display the menu. If I use negative margin and simply change bottom: -150 to bottom: 0px on click, it does produce the desired behavior by sliding it up from past the bottom of the window and it displays correctly. But it means the menu is pushing the page past the bottom of the page rather than simply being hidden. So when it's "hidden", one can simply scroll down and see the full menu which shouldn't be the case.
So rather than using bottom to manipulate it, I tried using $(this).show("slide"). The menu came out looking distorted thanks to using the sliding animation.
Here's the snippet:
var supTabState = false;
$("#dccontainer").css('bottom', '-150px');
$("#dcsupporttab").click(function() {
$('#dcsupportcontainer').slideToggle(500, function() {
//execute this after slideToggle is done
});
supTabState = !supTabState;
if (supTabState) {
// $("#dccontainer").css('bottom', '0px');
$(this).show("slide", {
direction: "down"
}, 1000);
} else {
// $("#dccontainer").css('bottom', '-150px');
$(this).show("slide", {
direction: "up"
}, 1000);
}
});
#dccontainer {
position: absolute;
bottom: 0;
width: 300px;
left: 50%;
height: 200px;
margin-left: -150px;
transition: .5s;
overflow: hidden;
}
#dccontainer * {
margin-top: 0;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
font-weight: bold;
/* font-family: 'Catamaran', 'Roboto', 'Helvetica', 'Arial', 'sans-serif'; */
}
#dcsupporttab {
background-color: #f5f5f5;
color: #434343;
text-align: center;
width: 150px;
padding: 10px;
padding-bottom: 3px;
margin: auto;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
cursor: pointer;
}
#dcsupportcontainer {
background-color: #f5f5f5;
padding-top: 10px;
color: #434343;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
/*height: calc(100% - 43px); */
display: none;
}
.dcbutton {
display: flex;
text-align: center;
background-color: #fff;
border-radius: 10px;
flex-direction: column;
justify-content: center;
align-items: center;
width: 230px;
height: 40px;
}
.dcthelabel {
text-decoration: none;
color: #434343;
text-transform: uppercase;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.nonsolid {
background-color: #f5f5f5;
border-color: #fff;
border-style: solid;
border-width: 3px;
}
#dcmessageus {
text-transform: none;
}
#dcaslnow {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="dccontainer">
<p id="dcsupporttab">Support</p>
<div id="dcsupportcontainer">
<div class="dcbutton" id="dcaslnow">
ASL Now
</div>
<div class="dcbutton" id="dctextchat">
Text Chat
</div>
<div class="dcbutton nonsolid" id="dcmessageus">
Send Us a Message
</div>
<p id="dcvpinfo">Video Chat: (123) 456-7890</p>
</div>
</div>
I've tried various techniques. I've tried toggling with CSS alone using CSS animation and toggleClass, I've tried using slide, and I've tried using slideToggle. I also tried using display: block; instead of using flexbox. Both had the same effect. Researching the internet yielded several possible solutions (which I've tried, but all came out with the same result), and those usually weren't based on an element being fixed at bottom of window. The only one that came closest to what I was looking for was this:
http://atomicrobotdesign.com/blog_media/toggleslide_multiple.html
But strangely, when I attempted to use the same code that used, nothing happened. Clicking did not bring up the menu. I'm at a loss at this point. Where am I going wrong?
This is my latest attempt (using above code): https://codepen.io/doncullen/pen/JjdrxzY
To answer your question Where am I going wrong: you're specifying a fixed height of 200px on #dccontainer. Specifying a fixed height to the container renders the jQuery's slideToggle useless. jQuery's slideToggle animates the height of the given element, and in your case, you're animating #dcsupportcontainer. Even though you're animating the height of #dcsupportcontainer to 0px using slideToggle, the whole support block will still remain 200px in height. This causes makes the whole block not to move down when the #dcsupportcontainer is gone. You can, of course, manually calculate and assign the new bottom value to #dccontainer, but that's a real hassle and really unintuitive.
Not wanting to calculate the bottom value myself, I will not set a height to #dccontainer and just let its height be. It will set its height to all its children's requirements (the default value is auto). Furthermore, instead of using fixed, you used absolute. You should use fixed here as you want the support block to always be visible (even when the user scrolls down); this means that you should position it based on your viewport and not an element (read more about positioning here). I also did minor adjustments on your CSS styles so that it's a tad more concise. One last thing, I suggest that you revisit flexbox here and here to utilise it better.
Here's a working solution:
// First time accessing, hide the support buttons section
$('#dcsupportcontainer').hide()
$("#dcsupporttab").click(function() {
$('#dcsupportcontainer').slideToggle(500)
});
* {
box-sizing: border-box;
margin: 0;
}
body {
min-width: 100vw;
min-height: 100vh;
}
#dccontainer {
position: fixed;
left: 50%;
bottom: 0px;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
width: 50vw;
min-width: 200px;
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
}
#dccontainer * {
padding: 7px 20px;
text-align: center;
}
#dcsupporttab {
font-weight: bold;
border-radius: 5px 5px 0 0;
background: #121212;
color: #ffffffee;
cursor: pointer;
}
#dcsupportcontainer {
border: 1px solid #121212;
border-radius: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="dccontainer">
<p id="dcsupporttab">Support</p>
<div id="dcsupportcontainer">
<div class="dcbutton" id="dcaslnow">
ASL Now
</div>
<div class="dcbutton" id="dctextchat">
Text Chat
</div>
<div class="dcbutton nonsolid" id="dcmessageus">
Send Us a Message
</div>
<p id="dcvpinfo">Video Chat: (123) 456-7890</p>
</div>
</div>
Just take the fixed height from your main container #dccontainer, and everything will be fine. You should also remove a few lines of your javascript code to fix everything. That fixed height of dccontainer makes the whole nav to stand 200px up from the bottom of your page and that makes you use more jQuery to fix it at the bottom. Remember that the bottom: 0px will set the bottom of your element at the 0px bottom of its container.
$("#dcsupporttab").click(function() {
$('#dcsupportcontainer').slideToggle(500, function() {
//execute this after slideToggle is done
});
});
#dccontainer {
position: absolute;
bottom: 0px;
width: 300px;
left: 50%;
margin-left: -150px;
transition: .5s;
overflow: hidden;
}
#dccontainer * {
margin-top: 0;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
font-weight: bold;
/* font-family: 'Catamaran', 'Roboto', 'Helvetica', 'Arial', 'sans-serif'; */
}
#dcsupporttab {
background-color: #f5f5f5;
color: #434343;
text-align: center;
width: 150px;
padding: 10px;
padding-bottom: 3px;
margin: auto;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
cursor: pointer;
}
#dcsupportcontainer {
background-color: #f5f5f5;
padding-top: 10px;
color: #434343;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
/*height: calc(100% - 43px); */
display: none;
}
.dcbutton {
display: flex;
text-align: center;
background-color: #fff;
border-radius: 10px;
flex-direction: column;
justify-content: center;
align-items: center;
width: 230px;
height: 40px;
}
.dcthelabel {
text-decoration: none;
color: #434343;
text-transform: uppercase;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.nonsolid {
background-color: #f5f5f5;
border-color: #fff;
border-style: solid;
border-width: 3px;
}
#dcmessageus {
text-transform: none;
}
#dcaslnow {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="dccontainer">
<p id="dcsupporttab">Support</p>
<div id="dcsupportcontainer">
<div class="dcbutton" id="dcaslnow">
ASL Now
</div>
<div class="dcbutton" id="dctextchat">
Text Chat
</div>
<div class="dcbutton nonsolid" id="dcmessageus">
Send Us a Message
</div>
<p id="dcvpinfo">Video Chat: (123) 456-7890</p>
</div>
</div>

How to always fill the parent height using flexbox?

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/

Categories