I have built a demo that shows button 2 appearing after 1 second of the page loading. However, the problem is that it moves the position of button 1 up, but I'd rather it not move at all.
I know this could be fixed by using position absolutes, not using space-between, etc, but I want to be able to fix this with the current CSS staying put.
How can this be fixed? I've tried to set the visibility from hidden to visible, but the problem with that is that it does not fade in nicely. Any ideas about the best tricks or tips to do this would be very helpful, thank you.
Codepen: https://codepen.io/anon/pen/KEWjNm
setTimeout(() => $('#btn-2').fadeIn('slow'), 1000);
div {
background: pink;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
width: 100%;
height: 100vh;
}
#btn-2 { display: none }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button id='btn-1'>button 1</button>
<button id='btn-2'>button 2</button>
</div>
To achieve expected result, use animate option with opacity: 0 for btn2 initially
setTimeout(() => $('#btn-2').animate({opacity:1}, 1000), 1000);
div {
background: pink;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
width: 100%;
height: 100vh;
}
#btn-2 { opacity: 0 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button id='btn-1'>button 1</button>
<button id='btn-2'>button 2</button>
</div>
codepen - https://codepen.io/nagasai/pen/oVZrMK
You can use container, then one div per button:
Where the container has styles:
div.container {
background: pink;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
width: 100%;
height: 100vh;
}
<div class='container'>
<div>
<button id='btn-1'>button 1</button>
</div>
<div>
<button id='btn-2'>button 2</button>
</div>
</div>
Related
I have a flex container that contains several items that have the flex-grow property set to 1 and a certain max-width.
I want to add an event listener to the group of items, but I do not want the event to fire if the event location is in the empty space of the flex container. For example, for a click event, I want the event to fire only if the blue space of the image below is clicked.
If I add the event listener to the parent container, the event fires even if I click the purple. If I add the event listener to the child items, the event does not fire when if I click on the margins of the items. In addition, for events like onmouseenter or onmouseleave, the event fires 3 times if I move my mouse over all the items, whereas my desire is for it to only fire once.
Here is a snippet of the current scenario:
$(".flex-container").on("mouseenter", () => {
$("#hidden").show();
})
$(".flex-container").on("mouseleave", () => {
$("#hidden").hide();
})
$(".flex-item").on("mouseenter", () => {
$("#hidden2").show();
})
$(".flex-item").on("mouseleave", () => {
$("#hidden2").hide();
})
.flex-container {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid black;
margin: 5px;
padding: 5px;
}
.item-container {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
}
.flex-item {
padding: 5px;
margin: 10px;
outline: 1px solid black;
flex: 1 1 auto;
height: 24px;
max-width: 24px;
display: flex;
align-items: center;
justify-content: center;
}
#hidden, #hidden2 {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-container">
<div class="flex-item">
1
</div>
<div class="flex-item">
2
</div>
<div class="flex-item">
3
</div>
</div>
<div id="hidden">
Flex Container Hovered
</div>
<div id="hidden2">
Flex Item Hovered
</div>
Adding an extra flex container as a wrapper achieves close to the intended effect, but the intention of the flex-grow property of the items is not preserved, as seen below.
The items do not grow to the max-width of the items to fill up the outer box. Here is a snippet of the above scenario:
$(".flex-container").on("mouseenter", () => {
$("#hidden").show();
})
$(".flex-container").on("mouseleave", () => {
$("#hidden").hide();
})
$(".flex-item").on("mouseenter", () => {
$("#hidden2").show();
})
$(".flex-item").on("mouseleave", () => {
$("#hidden2").hide();
})
$(".extra-wrapper").on("mouseenter", () => {
$("#hidden3").show();
})
$(".extra-wrapper").on("mouseleave", () => {
$("#hidden3").hide();
})
.flex-container {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid black;
margin: 5px;
padding: 5px;
}
.extra-wrapper {
display: flex;
}
.item-container {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
}
.flex-item {
padding: 5px;
margin: 10px;
outline: 1px solid black;
flex: 1 1 auto;
height: 24px;
max-width: 24px;
display: flex;
align-items: center;
justify-content: center;
}
#hidden, #hidden2, #hidden3 {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-container">
<div class="extra-wrapper">
<div class="flex-item">
1
</div>
<div class="flex-item">
2
</div>
<div class="flex-item">
3
</div>
</div>
</div>
<div id="hidden">
Flex Container Hovered
</div>
<div id="hidden2">
Flex Item Hovered
</div>
<div id="hidden3">
Extra Wrapper Hovered
</div>
How do I add an event listener to the items in a flex container when the items have a flex-grow and a max-width property?
Try this: https://jsfiddle.net/sean7777/zngdr51k/11/
How 2 make it work
It works because since margin does not count in mouseleave and mouseenter events, we use a wrapper element around the flex-item, wrap. The wrapper then gets assigned padding, and you attach the event listener to the wrapper.
This way you can simulate margin as padding and make it work with the event listner.
Note that you will have to assign width and height to the box. In the example, if you remove the width/height, it won't look right.
Building upon the suggested answer from #ourmandave, I came up with the following solution.
In this solution, I added a pseudo element to each flex-item so that I could include the elements' margins in the events' "hot spots" as they were called. I then used additional logic to prevent the event handlers from repeated triggers by using the event's related target. By checking where the cursor used to be upon mouseleave or mouseenter events, one can prevent the event handlers from being fired again when the mouse moves from one flex item to another flex item. This solution still preserves the desired effects of flex-grow and max-width.
$(".flex-container").on("mouseenter", () => {
$("#hidden").show();
})
$(".flex-container").on("mouseleave", () => {
$("#hidden").hide();
})
$(".flex-item").on("mouseenter", (e) => {
if (e.relatedTarget.className === "flex-item") return;
console.log('mouseenter fired');
$("#hidden2").show();
})
$(".flex-item").on("mouseleave", (e) => {
if (e.relatedTarget.className === "flex-item") return;
console.log('mouseleave fired');
$("#hidden2").hide();
})
.flex-container {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid black;
margin: 5px;
padding: 5px;
}
.item-container {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
}
.flex-item {
padding: 5px;
margin: 10px;
outline: 1px solid black;
flex: 1 1 auto;
height: 24px;
max-width: 24px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.flex-item::before {
content: '';
position: absolute;
inset: -10px -10px -10px -10px;
}
#hidden, #hidden2 {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-container">
<div class="flex-item">
1
</div>
<div class="flex-item">
2
</div>
<div class="flex-item">
3
</div>
</div>
<div id="hidden">
Flex Container Hovered
</div>
<div id="hidden2">
Flex Item Hovered
</div>
I have this div with three inner divs.
ONE - I am div TWO - I am div THREE - I am div
But in mobile it can only fit two divs in a row horizontally, I need divs after 2nd to step down.
Like this:
ONE - I am div TWO - I am div
THREE - I am div
How do I do this?
I am using flex.
Edit
I have added HTML code.
I am using React and other UI component and I tried to minimize it in HTML. It's something like this right now.
<div class="parent">
<div class="child">
<span>ONE</span>
<p>I am div</p>
</div>
<div class="child">
<p>TWO</p>
<p>I am div</p>
</div>
<div class="child">
<span>THREE</span>
<p>I am div</p>
</div>
<div>
.parent {
display: flex;
justify-content: space-around;
margin-bottom: 3rem;
white-space: nowrap;
}
.child {
display: flex;
align-items: center;
margin-left: 1rem;
margin-right: 1rem;
}
You can use flex-wrap to continue on the next line. justify-content will center the div
.outer {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
/* Styles below are for demonstration purposes */
.inner {
height: 50px;
width: 300px;
}
.red {
background: red;
}
.green {
background: green;
}
.blue {
background: blue;
}
<div class="outer">
<div class="inner red">A</div>
<div class="inner green">B</div>
<div class="inner blue">C</div>
</div>
This will work for responsive layout, and it also permits them to fit in one line, if the screen size allows it. You can use media query to set it for mobile only.
.outer{
display: flex;
flex-flow: wrap;
text-align: center;
}
.inner{
flex-grow: 1;
}
I have come across a problem whereby if I add rows to an overflow container some of the rows at the top are obscured. My real application is a bit more complicated than this in that it also adds things inside of the row, and if you pick a "wrong" option, then the top row gets hidden completely.
Is it possible to fit all of the rows inside of the container, so that when you scroll all the way to the top, you can always see the topmost row? Currently, depending on how many rows you have, a portion, or whole top row is hidden.
JsFiddle link.
And also code here:
window.onload = function() {
let addBtn = document.getElementById("addRow");
addBtn.addEventListener('click', function() {
let wrapper = document.getElementById("wrapper");
let newRow = "<div class='row'></div>"
wrapper.innerHTML += newRow;
})
};
body {
display: flex;
justify-content: center;
}
#wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 40vh;
width: 1000px;
background-color: yellow;
overflow-y: auto;
}
.row {
display: block;
background-color: aliceblue;
min-height: 50px;
margin-top: 10px;
width: 80%;
}
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<div id="wrapper">
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
<div>
<button id="addRow">Add</button>
</div>
</body>
</html>
Remove align-item: center from #wrapper.
The problem is this property align all children rows in the middle of parent #wrapper.
So if you count the rows it's just the half of rows that should be appeared.
Try to inspect it, half of rows are above #wrapper which can't be viewed.
you can also have some padding to #wrapper to have some color below the last row.
check this Fiddle
Updated fiddle with the solution - https://jsfiddle.net/zL61c84x/
#wrapper {
height: 40vh;
width: 1000px;
background-color: yellow;
overflow-y: auto;
}
#wrapperInner {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
}
$(".div3Btn").click(function() {
$(".div2").show("slide", {
direction: "up"
}, 5000);
});
.div1 {
display: flex;
height: 100%;
flex-direction: column;
background-color: #919191;
}
.div2 {
display: flex;
overflow-y: auto;
flex: 1;
height: 500px;
background-color: #a8d810;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="div1">
<div class="div2" style="display: none;">hjghjgjghj</div>
<div class="div3">
<button class="div3Btn">Click me!</button>
</div>
</div>
I have a question about using the show()/hide() function with time and direction. As the above snippet shows, if the button was clicked, it will immediately jump to the bottom, but not following the div1 to slide down. Then how can I fix it if I want to use that function?
$(".div3Btn").click(function() {
$(".div2").slideToggle(5000);
});
.div1 {
display: flex;
height: 100%;
flex-direction: column;
background-color: #919191;
}
.div2 {
display: flex;
overflow-y: auto;
flex: 1;
height: 500px;
background-color: #a8d810;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="div1">
<div class="div2" style="display: none;">hjghjgjghj</div>
<div class="div3">
<button class="div3Btn">Click me!</button>
</div>
</div>
(The problem is quite similar to using Firefox to run the link function)
Another question about slide down and up is when I use flex: 1 for some divs, and then use the slideToggle() function, it does not have any slide down or up animation of the div. How to fix it if I must use flex: 1 for divs?
I think you've formatted the .show() function wrong. Try .show( duration [, easing ] [, complete ] )
$(".div3Btn").click(function() {
$(".div2").show(5000, "swing", function() {
// Animation complete.
});
});
.div1 {
display: flex;
height: 100%;
flex-direction: column;
background-color: #919191;
}
.div2 {
display: flex;
overflow-y: auto;
flex: 1;
height: 500px;
background-color: #a8d810;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="div1">
<div id="div2" class="div2" style="display: none;">hjghjgjghj</div>
<div class="div3">
<button id="div3Btn" class="div3Btn">Click me!</button>
</div>
</div>
I currently have a ReactJS + React Router project set up and in Chrome dev tool under elements shows:
<body>
<div class="wrapper">
<div data-reactroot>
<div>
<div class="container">Center Me</div>
</div>
</div>
</div>
</body>
with styling and none for class="wrapper":
.container {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
Yet the <div class="container">Center Me</div> is staying at the top and centered horizontally but not vertically.
I checked the size of that div and it is extremely short but takes up full width of the browser page.
What could I be doing wrong? How can I center <div class="container">Center Me</div>? I even tried to set 100% for width and height on a higher level, but still does not work.
Just:
<div style={{display: 'flex', justifyContent:'center', alignItems:'center', height: '100vh'}}>
<h1> I am centered </h1>
</div>
or css:
.centered {
height: 100vh; /* Magic here */
display: flex;
justify-content: center;
align-items: center;
}
<div class="centered">
<h1> I am centered </h1>
</div>
Here's a code example that basically recreates your page but without react. Hope this helps and shoot away if you have any questions.
html, body{
width: 100%;
height: 100%;
}
.wrapper{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.container {
height: 300px;
width: 300px;
background: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
<html>
<body>
<div class="wrapper">
<div data-reactroot>
<div class="container">
<div>
<!-- Anything below this line will be centered -->
<div>Hello World!</div>
<div>Center Me</div>
<!-- Anything above this line will be centered -->
</div>
</div>
</div>
</div>
</body>
<html>
I just wrap my div with Grid and added justify="center" attr.:
<Grid container spacing={2} justify="center"></Grid>
Yes, for react,
for becomes htmlFor, and class becomes className etc.
see full list of how HTML attributes are changed here:
https://facebook.github.io/react/docs/dom-elements.html
const App = () => {
const styles = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
};
return (
<div style={styles}>
<h2>Hello All</h2>
</div>
);
};
export default App;
In React You need to use className not class. className="wrapper