Reputation: 8319
My goal is to build a breadcrumb style component which:
Flexbox seems like a good place to start, but when it comes to requirements 3&4 I am not sure what the best approach is.
Here's my thought process so far:
a) To start, I could create a flexbox with items like so, each 100px wide:
https://codepen.io/mattwilson1024/pen/LLvMzB
b) Now let's imagine we only have 300px for the container. I could have all items shrinkable (flex: 0 1 100px
). This would be fine for a small number of items, but if I have a lot of items they'd all get too small.
https://codepen.io/mattwilson1024/pen/pwBqdN
What I really want is for it to only show as many items as will fit into the container. In this case that would be items 7-9.
c) Enabling flex-wrap: wrap
means each row only shows as many items as can fit. This is closer to what I'm after, except I'd only want the bottom row.
https://codepen.io/mattwilson1024/pen/YQMdEB
d) Media queries might help. For example I could use a media query to hide all but the last 3 items on a small screen, and all but the last 6 items on a larger screen etc. However, I would then need to know exactly where the component is going to be used and tweak the numbers accordingly. I'd rather find a solution that is based on the size of the container rather than the size of the viewport.
Upvotes: 4
Views: 3701
Reputation: 87251
You need to make 3 adjustments (in your last sample) to fulfill your requirements:
On the flex container items
flex-wrap: wrap
justify-content: flex-end
On the flex items item
last child
margin-right: auto
It works like this, where the flex-end
will right align the items making the last items the visible ones.
The margin-right: auto
will make the items left aligned when there are less items to fill the container.
Update codepen, where I also gave flex items a max-width
and changed flex to flex: 0 0 auto
, so they adjust to content and get ellipsis when they exceed the max width.
In the below Stack snippet I changed the flex-shrink
from 1 to 0 in flex: 0 0 100px
so it clearly shows how it behaves:
.items {
width: 300px;
display: flex;
justify-content: flex-end;
}
.item {
flex: 0 0 100px;
/* Truncate text with ellipsis */
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.item:last-child {
margin-right: auto;
}
/* Styling - not relevant to the question, just to make it look good */
.item {
border-right: solid 1px black;
box-sizing: border-box;
}
.item:nth-child(1) {
background-color: #e3f2fd;
color: black;
}
.item:nth-child(2) {
background-color: #bbdefb;
color: black;
}
.item:nth-child(3) {
background-color: #90caf9;
color: black;
}
.item:nth-child(4) {
background-color: #64b5f6;
color: black;
}
.item:nth-child(5) {
background-color: #42a5f5;
color: white;
}
.item:nth-child(6) {
background-color: #2196f3;
color: white;
}
.item:nth-child(7) {
background-color: #1e88e5;
color: white;
}
.item:nth-child(8) {
background-color: #1976d2;
color: white;
}
.item:nth-child(9) {
background-color: #1565c0;
color: white;
}
body {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
font-size: 14px;
}
body > div:nth-child(2) {
font-family: sans-serif;
font-size: 12px;
}
<div class="items">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
</div>
<div><br>If less to fit the container, they align left<br><br></div>
<div class="items">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
</div>
Updated
Based on a comment, where an item can't be chopped of, one can use row-reverse
, flex-end
and order
to make them start at the bottom right corner.
With this they can wrap upwards and by adding overflow: hidden
only the one's that fit within the containers width will be visible
.items {
width: 300px;
height: 15px;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
justify-content: flex-end;
overflow: hidden;
}
.item {
flex: 0 0 auto;
max-width: 100px;
padding: 0 10px;
/* Truncate text with ellipsis */
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/* Styling - not relevant to the question, just to make it look good */
.item { border-right: solid 1px black; box-sizing: border-box; }
.item:nth-child(1) { background-color: #e3f2fd; color: black; order: 10; }
.item:nth-child(2) { background-color: #bbdefb; color: black; order: 9; }
.item:nth-child(3) { background-color: #90caf9; color: black; order: 8; }
.item:nth-child(4) { background-color: #64b5f6; color: black; order: 7; }
.item:nth-child(5) { background-color: #42a5f5; color: white; order: 6; }
.item:nth-child(6) { background-color: #2196f3; color: white; order: 5; }
.item:nth-child(7) { background-color: #1e88e5; color: white; order: 4; }
.item:nth-child(8) { background-color: #1976d2; color: white; order: 3; }
.item:nth-child(9) { background-color: #1565c0; color: white; order: 2; }
body {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
font-size: 14px;
}
<div class="items">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
</div>
<div><br>If less to fit the container, they align left<br><br></div>
<div class="items">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
</div>
Upvotes: 6