I have got a basic flexbox grid. If I move the ngFor loop into a component (<comp-ngfor-testGrid></comp-ngfor-testGrid>) the flex is broken.
The <comp-ngfor-testGrid> on the DOM causes the issue. I would like to remove it and keep only the content of the component <comp-ngfor-testGrid>.
:host {} is not the solution because the <comp-ngfor-testGrid> still exist...
.grid {
display: flex;
justify-content: space-between;
width: 100%;
flex-wrap: wrap;
div {
width: calc(50% - 10px);
margin-bottom: 15px;
}
}
testGrid = [4,5,6];
<div class="grid">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div *ngFor="let item of testGrid ">
{{item}}
</div>
<comp-ngfor-testGrid></comp-ngfor-testGrid>
</div>
Related
My scenario
I have these two flex containers (the difficulty options and the max-score options):
I want the 'easy', 'medium' and 'hard' button to share the same width, but also to fit they're content (in this case, because 'medium' is the longest, they should all equal its width).
I want the same behavior with the bottom buttons (but for them to have a smaller width since they need to accommodate for smaller content).
Right now the flex containers for both of them is set to:
display: flex;
flex-direction: wrap;
flex-wrap: wrap;
And the flex children are each set to their default flex values, with a set height and an auto width.
Approaches I've tried
First approach - flex-basis and flex-grow
Setting the children to flex-basis: 0 and flex-grow: 1, as I've seen in past questions, but then my wrapped child fills the entire width, and the top buttons aren't the same width:
Second approach - -- hardcoded flex-basis
Setting all children to flex-basis: 90px (90px to accommodate for the biggest button, 'medium') which does make them all the same width, but then the width is fixed and doesn't adjust to only fit the content (specifically this is desired so the score buttons can fit in two rows instead of three).
Third approach - max-width
The closest I've got to is to set the children to:
```
max-width: 90px;
flex-basis: 0;
flex-grow: 1;
```
Which makes them behave as wanted:
But when the screen width shrinks, the buttons start to differ in width (the obvious one is the '200' button bigger than the other scores, but also 'medium' is bigger than 'easy' and 'hard'):
My code:
.flex-col,
.flex-row {
display: flex;
flex-wrap: wrap;
gap: 4px;
justify-content: center;
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.button {
border-style: solid;
padding: 4px;
}
.parent {
height: auto;
width: auto;
}
<div class="parent flex-col">
<div class="flex-col">
<div class="flex-row">
DIFFICULTY
</div>
<div class="flex-row">
<div class="button">EASY</div>
<div class="button">MEDIUM</div>
<div class="button">HARD</div>
</div>
</div>
<div class="flex-col">
<div class="flex-row">
MAX SCORE
</div>
<div class="flex-row">
<div class="button">50</div>
<div class="button">75</div>
<div class="button">100</div>
<div class="button">150</div>
<div class="button">200</div>
</div>
</div>
</div>
Help appreciated, thanks!
The closest way to do this with CSS only, is to use a grid instead of a flexbox for reasons well explained here.
The only way to truly do what you are asking (make all children have the same width as the widest child), is with JavaScript. Loop through the elements to find the biggest width and set them all to have the found width.
Here is a snippet demonstrating both concepts:
const equalizers = document.querySelectorAll('.equalize')
let r = 0
equalizers.forEach(equalizer => {
const widths = []
for (const btn of equalizer.children) {
const w = btn.getBoundingClientRect().width
// Math.ceil() is optional to avoid long floats
widths.push(Math.ceil(w)) // 82
// widths.push(w) // 81.31945037841797
}
const biggest = Math.max(...widths)
console.log(`biggest width found in row[${r++}]:`, biggest)
for (const btn of equalizer.children) {
btn.style.width = `${biggest}px`
}
})
.flex-col,
.flex-row {
display: flex;
flex-wrap: wrap;
gap: 4px;
justify-content: center;
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.button {
border-style: solid;
padding: 4px;
}
.parent {
height: auto;
width: auto;
}
.grid-row {
display: grid;
gap: 4px;
}
.grid-row>* {
text-align: center;
}
#media (min-width: 25em) {
.grid-row {
grid-auto-flow: column;
grid-auto-columns: 1fr;
}
}
.flex-row>* {
text-align: center;
}
<hr>
<strong>JavaScript</strong> (only ever as wide as the widest sibling, with wrapping)
<hr>
<div class="parent flex-col">
<div class="flex-col">
<div class="flex-row">
DIFFICULTY
</div>
<div class="flex-row equalize">
<div class="button">EASY</div>
<div class="button">MEDIUM</div>
<div class="button">HARD</div>
</div>
</div>
<div class="flex-col">
<div class="flex-row">
MAX SCORE
</div>
<div class="flex-row equalize">
<div class="button">50</div>
<div class="button">75</div>
<div class="button">100</div>
<div class="button">150</div>
<div class="button">200</div>
</div>
</div>
</div>
<hr>
<strong>Grid</strong> (always as wide as posible and no wrapping, either all stacked, or all inline with breakpoint)
<hr>
<div class="parent flex-col">
<div class="flex-col">
<div class="flex-row">
DIFFICULTY
</div>
<div class="grid-row">
<div class="button">EASY</div>
<div class="button">MEDIUM</div>
<div class="button">HARD</div>
</div>
</div>
<div class="flex-col">
<div class="flex-row">
MAX SCORE
</div>
<div class="grid-row">
<div class="button">50</div>
<div class="button">75</div>
<div class="button">100</div>
<div class="button">150</div>
<div class="button">200</div>
</div>
</div>
</div>
In the example below, the Add Role div is on a new line instead of being next to Role 5.
How to get them to be next to each other using css without them being in the same container (.roles for example)?
.role, .new-role {
height: 5rem;
width: 5rem;
margin: 1rem;
background-color: green;
display: block;
}
.roles {
display: inline-flex;
flex-wrap: wrap;
}
.outside {
display: inline-flex;
width: 15rem;
flex-wrap: wrap;
}
<div class="outside">
<div class="roles">
<div class="role">
Role 1
</div>
<div class="role">
Role 2
</div>
<div class="role">
Role 3
</div>
<div class="role">
Role 4
</div>
<div class="role">
Role 5
</div>
</div>
<div class="new-role">
Add Role
</div>
</div>
A workaround to put the Add Role besides Role5 under Role4 you could use position like so (at least works in codepen)
.new-role{
position:absolute;
top:14.5rem;
left:7.5rem;
}
#role5{
position:relative;
}
I'm trying to position the react components and having hard time figuring out with CSS flexbox.
I have 3 react components as below
function App() {
return (
<>
<div className = "header">
<h1>Connect cruAMS and Security Center</h1>
</div>
<br></br>
<div className="App">
<Cruams />
<SecurityCenter />
<UserContainer />
</div>
</>
);
}
Currently it's location is like below.
Cruams SecurityCenter UserContainer
What I want is
Cruams SecurityCenter
UserContainer
How can I do this using CSS flexbox? Or is there a different way?
Thanks in advance!
If you don't want to make your css too complicated, a simple top margin can help you here:
.App {
display: flex;
justify-content: center;
}
.cruams {
display: inline-block;
}
.securityCenter{
display: inline-block;
margin-top: 20px;
}
.userContainer {
display: inline-block;
}
<div className = "header">
<h1>Connect cruAMS and Security Center</h1>
</div>
<br></br>
<div class="App">
<div class="cruams">cruams</div>
<div class="securityCenter">securityCenter</div>
<div class="userContainer">userContainer</div>
</div>
Without using any extra divs:
<div className="container">
<Cruams className="half-width" />
<SecurityCenter className="half-width"/>
<UserContainer className="full-width" />
</div>
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.half-width {
flex-basis: 50%
}
.full-width {
flex-basis: 100%
}
I am trying to place my card boxes on 1 row rather than on 1 column. Can someone explain to me what is wrong with this CSS?
import "./Card.css"
class Card extends PureComponent {
render() {
return (
<div className="cardcontainer">
<div className="cardbox">
<div>{this.props.title}</div>
<div>{this.props.category}</div>
<div>{this.props.likes / this.props.dislikes}</div>
</div>
</div>
)
}
}
export default Card
.cardcontainer{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.cardbox{
border: 1px solid red;
width: 200px;
height: 200px;
}
Your cardlist style needs to be applied with the parent component of the Card component.
EG you may have another component called cardList and within the render method for that you apply the cardcontainer style EG.
<div className = cardcontainer>
<Card/>
</div>
This is because in your current code you have initiated the cardcontainer style for every row. I have recoded your work in CSS and HTML so you can see what I mean. I hope this helps.
.cardcontainer{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width:1000px;
}
.cardbox{
border: 1px solid red;
width: 200px;
height: 200px;
}
<div class="cardcontainer">
<div class="cardbox">
<div>A title</div>
<div>A CAtegory</div>
</div>
<div class="cardbox">
<div>A title</div>
<div>A CAtegory</div>
</div>
</div>
I am using Materializecss to create React app. I have already applied flex inside my app class. And now I want to apply flex inside main tag where buttons get fixed at bottom of main tag & above the footer.
I have tried {margin-top: auto;} , justify-content: flex-end which didn't help. The buttons always print after content class. I can set the height of the content class, but small devices render view badly and it's not fixing my problem.
JSX code:
<div className="app">
<header> <header>
<main>
<div className="box">
<div className="content"> Long text less than 100 words <div>
<div className="buttons"> <button> Button-1 </button> <button> Button-2 </button>
<div>
<main>
<footer><footer>
<div>
My css
app {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1 0 auto;
}
I want to stick my button above the footer. My content class has 100 words then the button should stick above the footer not rendered after the content class.
I would appreciate the help.
You haven't applied display:flex etc to the main element. If you do that the margin-top:auto will work.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
.app {
display: flex;
min-height: 100vh;
flex-direction: column;
background: ;
}
main {
flex: 1;
display: flex;
flex-direction: column;
}
.buttons {
margin-top: auto;
}
<div class="app">
<header>header </header>
<main>
<div class="box">box</div>
<div class="content"> Long text less than 100 words </div>
<div class="buttons">
<button> Button-1 </button>
<button> Button-2 </button>
</div>
</main>
<footer>footer</footer>
</div>