I'm working to create a component similar to Chosen, but I'm running into an issue with flex and wrapping. The gist is that each "chip" in the pseudo textbox needs to be in a container that does not also contain the actual text input, but I need those chips to be treated as a flex element on the same basis as the input
.
My HTML structure looks like this:
<div class="box">
<div class="chipContainer">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
</div>
<input class="textbox" type="text">
</div>
This Plunker example is more complete and has styles roughly equivalent to what I'm working with currently.
.box {
background: #fff;
border: 1px solid #ccc;
width: 500px;
overflow: auto;
padding: 2px;
display: flex;
flex-wrap: wrap;
}
.chip {
display: inline-block;
border: 1px solid #ccc;
background: #eee;
padding: 2px;
margin-right: 1px;
flex: auto;
}
.textbox {
border: none;
background: #fdd;
font-size: 18px;
flex: auto;
}
.textbox:focus {
outline: none;
}
.chipContainer {
display: inline;
}
<div class="box">
<div class="chipContainer">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
</div>
<input class="textbox" type="text">
</div>
<br>
<div class="box">
<div class="chipContainer">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
<div class="chip">Chip5</div>
<div class="chip">Chip6</div>
<div class="chip">Chip7</div>
<div class="chip">Chip8</div>
<div class="chip">Chip9</div>
<div class="chip">Chip10</div>
<div class="chip">Chip11</div>
</div>
<input class="textbox" type="text">
</div>
As you can see, after enough chips have been added to the .box
container the .chipContainer
will begin to wrap them, but .chipContainer
remains a block element and pushes the input
down to a new line entirely.
This Plunker example demonstrates my goal. The layout can be achieved fairly easily once .chipContainer
is removed, however it's a fairly essential element in the component's structure, and I would prefer to solve this without removing it, if possible.
.box {
background: #fff;
border: 1px solid #ccc;
width: 500px;
overflow: auto;
padding: 2px;
display: flex;
flex-wrap: wrap;
}
.chip {
display: inline-block;
border: 1px solid #ccc;
background: #eee;
padding: 2px;
margin-right: 1px;
flex: auto;
min-width: 50px;
max-width: 60px;
}
.textbox {
border: none;
background: #fdd;
font-size: 18px;
flex: auto;
min-width: 250px;
}
.textbox:focus {
outline: none;
}
.chipContainer {
display: inline;
}
<div class="box">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
<input class="textbox" type="text">
</div>
<br>
<div class="box">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
<div class="chip">Chip5</div>
<div class="chip">Chip6</div>
<div class="chip">Chip7</div>
<div class="chip">Chip8</div>
<div class="chip">Chip9</div>
<input class="textbox" type="text">
</div>
You can use flex-shrink: 0 on the child elements to keep them from shrinking to fill the container. And use flex-wrap: wrap on the container/wrapper so your children will wrap down. Save this answer.
To prevent horizontal overflow, you can: Use flex-basis: 0 and then let them grow with a positive flex-grow . Use a positive flex-shrink to let them shrink if there isn't enough space.
display. This defines a flex container; inline or block depending on the given value. It enables a flex context for all its direct children. Note that CSS columns have no effect on a flex container.
This means that if you have a set of flex items that are too wide for their container, they will overflow it. If you want to cause them to wrap once they become too wide you must add the flex-wrap property with a value of wrap , or use the shorthand flex-flow with values of row wrap or column wrap .
Display Module Level 3 instroduces display: contents
:
The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree.
So you just need
.chipContainer {
display: contents;
}
.box {
background: #fff;
border: 1px solid #ccc;
width: 500px;
overflow: auto;
padding: 2px;
display: flex;
flex-wrap: wrap;
}
.chip {
display: inline-block;
border: 1px solid #ccc;
background: #eee;
padding: 2px;
margin-right: 1px;
flex: auto;
min-width: 50px;
max-width: 60px;
}
.textbox {
border: none;
background: #fdd;
font-size: 18px;
flex: auto;
}
.textbox:focus {
outline: none;
}
.chipContainer {
display: contents;
}
<div class="box">
<div class="chipContainer">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
</div>
<input class="textbox" type="text">
</div>
<br>
<div class="box">
<div class="chipContainer">
<div class="chip">Chip1</div>
<div class="chip">Chip2</div>
<div class="chip">Chip3</div>
<div class="chip">Chip4</div>
<div class="chip">Chip5</div>
<div class="chip">Chip6</div>
<div class="chip">Chip7</div>
<div class="chip">Chip8</div>
<div class="chip">Chip9</div>
<div class="chip">Chip10</div>
<div class="chip">Chip11</div>
</div>
<input class="textbox" type="text">
</div>
However, note it's not widely supported yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With