I have a set of tags, that I want to show in the client. However, sometimes you might have too many tags and you want to show only one row of tags maximized to your body's width without setting a fixed number of columns or item width, and adding a show more button at the end of the tag list with the same style as a tag.
I have achieved this using Javascript in my Angular project by doing the following:
let contentWidth = this.contentContainer.nativeElement.clientWidth;
Calculating text function does the following:
const canvas = document.createElement('canvas'); // create a canvas
const context = canvas.getContext('2d'); // get the context
context.font = '12px avertastd-bold'; // set up your font and size
And calculate the text width:
const seeMoreButtonWidth = context.measureText(seeMoreButtonText).width;
(Not runnable here)
for (const tag of this.data.tags) { const width = context.measureText(tag).width; if (contentWidth - (width + this.tagsPadding) > 0) { previewTags.push({text: tag}); contentWidth -= (width + this.tagsPadding); } else { break; } }
previewTags
list: previewTags.push({text: seeMoreButtonText, isButton: true});
And it looks like this in the html:
<ng-container *ngFor="let tag of previewTags">
<div class="tag" [ngClass]="{'see-more-button': tag.isButton}">{{tag.text}}</div>
</ng-container>
Output:
Resize:
As you see, now the tags are flexiable (this code does not include the show more functionality).
After giving you this background and understanding of what I am doing, I would love to ask if this is possible to achieve with css or less JavaScript intervation?
Something like this could be a pure css solution if your tags have a constant height. I just let the flex-list wrap around and then don't show the overlap.
.content_wrapper { display: flex; justify-content: flex-start; flex-direction: rows; }.tag_wrapper { display: flex; justify-content: flex-start; flex-direction: rows; flex-wrap: wrap; width: 80%; height: 32px; overflow: hidden; }.tag_wrapper div { width:100px; height:30px; border: 1px solid black; } button { flex-grow: 4; }
<div class="content_wrapper"> <div class=tag_wrapper> <div>Tag1</div> <div>Tag2</div> <div>Tag3</div> <div>Tag4</div> <div>Tag5</div> <div>Tag6</div> <div>Tag7</div> <div>Tag8</div> <div>Tag9</div> </div> <button>See more</button>
You could probably make the "See more" button solution more elegant, to not have as much white space but I'll leave that to you:)
Here is some javascript to remove the see-more button if it's not needed.
(OBS) this only works if all the tags are the exact same width and have the same margin. I did this to avoid looping through all values and checking their width individually.
(I know the list is in the wrong order, I made it like that to get the see-more button fit in well without having to tinker a bunch.
function getWidthWithMargin(elem) { var style = elem.currentStyle || window.getComputedStyle(elem) margin = parseFloat(style.marginLeft) + parseFloat(style.marginRight) return(elem.getBoundingClientRect().width + margin) } function handleWindowSizeChange() { let tags = document.getElementsByClassName("tag"); if(tags.length;= 0) { let tag_width = getWidthWithMargin(tags[0]). if(tags[0].parentElement.getBoundingClientRect().width/tag_width > tags.length) { document.getElementById("see-more-button").style;display = "none". } else{ document.getElementById("see-more-button").style;display = "block". } } } window;onload = handleWindowSizeChange. window;onresize = handleWindowSizeChange;
.content_wrapper { }.tag_wrapper { display: flex; justify-content: flex-start; flex-direction: row-reverse; flex-wrap: wrap; width: 100%; height: 32px; overflow: hidden; }.tag_wrapper div { min-width:100px; height:30px; border: 1px solid black; margin: 10px; }.tag_wrapper button { height:30px; flex-grow: 50; }
<div class="content_wrapper"> <div class=tag_wrapper> <button id="see-more-button">See more</button> <div class="tag">Tag1</div> <div class="tag">Tag2</div> <div class="tag">Tag3</div> <div class="tag">Tag4</div> <div class="tag">Tag5</div> <div class="tag">Tag6</div> <div class="tag">Tag7</div> <div class="tag">Tag8</div> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.