I have a mat-list in an Angular component like below (food-list.component.html)
<mat-list id="site-list">
<ng-container *cdkVirtualFor="let food of foods">
<mat-list-item id="food-{{food.id}}">
<mat-icon *ngIf="showFoodIcon" color="warn">not_listed_location</mat-icon>
<p matLine [ngStyle]="{width: foodLabelWidth} class="overflowText"><small>{{food.label}}</small></p>
<p matLine [ngStyle]="{width: foodLabelWidth} class="overflowText"><small>{{food.type}}</small></p>
</mat-list-item>
</ng-container>
</mat-list>
And in CSS file (food-list.component.scss)
p.overflowText {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
As example in a desktop view mat list item width 100px and, MatIconWidth is 5px. and in mobile view mat list item width 50px and, MatIconWidth is 5px. I want to set text overflow width according to the space that left.
for example, in food-list.component.ts I want to do something like this.
ngOnInit(): void {
this.foodLabelWidth= matListItemWidth - MatIconWidth;
}
to make it happen I want to get DOM element width of
<mat-icon *ngIf="showFoodIcon" color="warn">not_listed_location</mat-icon>
Which lies inside a NgFor loop. Is there a way to achieve this?
So I could use flex design to make it work !!
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
in html file
<mat-list id="site-list">
<ng-container *cdkVirtualFor="let food of foods">
<mat-list-item id="food-{{food.id}}">
<div class="flex-row w-100">
<div class="flex-row">
<mat-icon *ngIf="showFoodIcon" color="warn">not_listed_location</mat-icon>
</div>
<div class="food-title">
<p matLine class="overflowText"><small>{{food.label}}</small></p>
<p matLine class="overflowText"><small>{{food.type}}</small></p>
</div>
</div>
</mat-list-item>
</ng-container>
</mat-list>
scss file
::ng-deep .cdk-virtual-scroll-content-wrapper {
max-width: 100%
}
.flex-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.overflow {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.food-title {
flex-grow: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
Related
Right now I am trying to make my modal responsive but the "SAVE" button is not positioning as i want it to.
I want to have the button at the same position all the time, but right now it is disappearing.
My HTML and css looks as the following
.delete{
font-size: 16px;
max-width: 100%;
max-height: 60vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.delete .text-div{
padding: 3px;
}
.delete .button-div{
display: inline-block;
position: relative;
padding: 3px;
/* right: 50%;*/
left: 80%;
}
<div class="delete">
<div class="dialog-content-wrapper">
<mat-toolbar matDialogTitle class="mat-accent m-0">
<mat-toolbar-row fxLayout="row" fxLayoutAlign="space-between center">
<span class="title dialog-title">Delete Entry</span>
<button mat-icon-button (click)="onClose()" aria-label="Close dialog">
<mat-icon>close</mat-icon>
</button>
</mat-toolbar-row>
</mat-toolbar>
</div>
<div class="text-div">
<span>Are you sure you want to delete this vacation entry?</span>
</div>
<div class="button-div">
<button mat-raised-button color="accent" class="button" (click)="buttonClick();onClose()">SAVE</button>
</div>
</div>
First off, you don't need to wrap single elements into divs, it's not a very good practice regarding accessibility.
Regarding your question, where exactly do you want your button to be? If its position is set to relative, it will be positioned relative to the nearest positioned ancestor. That means that you need to put a position property to the .delete div (usually, relative will suffice).
Another way to achieve what you want (if I understand it correctly) would be adding align-self: end to the button element, since it's wrapped inside a flex container.
I am trying to give some margins between the buttons (Reset Filter/Apply Filter/Save & Apply Filter)in UI, I have used flex to align the buttons, but I am not able to give some margins/gaps between the buttons.
Any idea how to do it
Code :
<div class="d-flex flex-column justify-space-around">
<v-btn
text
style="margin-left: 30px"
color="primary"
#click="resetFilter()">
Reset Filter
</v-btn>
<v-btn
v-if="!updatingSavedFilter"
color="primary"
#click="
applyFilter()
filterDropdownOpen = false">
Apply Filter
</v-btn>
<v-btn
color="primary"
#click="
validateAndSaveFilter()
filterDropdownOpen = "false">
Save & Apply Filter
</v-btn>
</div>
It appears you're using Vuetify, am I right? In that case, you could add a margin class to each button:
<v-btn
text
style="margin-left: 30px"
color="primary"
class="mb-2"
#click="resetFilter"
>
Reset Filter
</v-btn>
See Vuetify's spacing documentation.
On another subject: try to avoid inline style. Better add a class. In this case you can have something like
class="mb-2 ml-7"
That will give you 8px margin on the bottom and 28px margin on the left.
Also, when passing function name to #click, don't execute it, only pass the name (see my example above).
You have to set a height to be able to use justify-content: space-around. Like in this example:
.box {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 300px;
}
.box button {
height: 50px;
width: 200px;
}
<div class='box'>
<button>Button</button>
<button>Button</button>
<button>Button</button>
</div>
Or you can use the new gap property.
.box {
display: flex;
flex-direction: column;
justify-content: space-around;
gap: 20px;
}
.box button {
height: 50px;
width: 200px;
}
<div class='box'>
<button>Button</button>
<button>Button</button>
<button>Button</button>
</div>
Or just set a margin-top
.box {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.box button {
height: 50px;
width: 200px;
}
.box button:not(:first-child) {
margin-top: 20px;
}
<div class='box'>
<button>Button</button>
<button>Button</button>
<button>Button</button>
</div>
There is a universal css solution to set gap between flex items using the following CSS, instead of adding styles/classes to each child element:
.d-flex{
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px; /* sets only for rows */
column-gap: 20px; /* sets only for columns */
}
Reference:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/#flexbox-background
I've got two images that need to be aligned on either side of the title, preferable on the edges of the page. I tried to use position relative but it's not responsive to other screen sizes.
Can someone show me an efficient way to do this, please?
Currently its like this, but i want the two images to be on either side of the title.
title{
width: 100%;
}
.web{
font-size: 120px;
}
.js{
height: 230px;
width: 240px;
}
.css{
height: 230px;
width: 440px;
}
<div class="intro py-3 bg-white text-center">
<img class="js" src="images/js-flat.png" alt="js">
<div class="title">
<h2 class="web text-primary display-3 my-4">Wev Dev Quiz</h2>
<img class="css" src="images/css2.png" alt="css">
</div>
</div>
never-mind, i fixed it with:
.intro {
display: flex;
justify-content: center;
flex-direction: row;
align-items: center
}
You can use display:flex property in your parent div. I did some changes of your html and css codes below.
Here is the html part. I deleted the div that has a title class because all elements that are needed to be align should be seperated each other if you use display:flex
Here is the HTML and CSS codes:
.intro {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center
}
.web{
font-size: 120px;
}
.js{
width: 240px;
}
.css{
width: 240px;
}
<div class="intro bg-white ">
<img class="js" src="images/js-flat.png" alt="js">
<h2 class="web text-primary">Wev Dev Quiz</h2>
<img class="css" src="images/css2.png" alt="css">
</div>
When you use display:flex all items are aligned as horizontally. But we want to align them vertically. So we need to use flex-direction:column (its default is row). To align these items center, we also need align-items because this is used to align in cross axis which is perpendicular to the main axis.
Codepen: you can check it here
In my javascript app, I have list of clickable options that I am getting from an api.
I want to adjust button size, according to longest text in the button list.
Setting fixed width would not work, because there will be different option text in different pages.
Below I have illustrated how I want to display my buttons.
Currently, my app shows like illustration no.1 but i need to show it like in the 2nd one.
Could any css trick make this happen?
You can use flex
Flex items can share equal widths if they are siblings.
https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction
.parent {
display: flex;
}
.container {
display: flex;
flex-direction: column;
}
<div class='parent'>
<div class="container">
<button>label label label label</button>
<button>button</button>
<button>button</button>
<button>button</button>
<button>button button</button>
</div>
</div>
You can use the display:table option:
https://jsfiddle.net/falkedesign/bjxL1atd/
.table {
display: table;
}
.torw {
display: table-row;
}
.tcell {
display: table-cell;
}
div {
border: 1px solid #000;
}
button {
width: 100%;
}
<div class="table">
<div class="trow"><button>BTN</button></div>
<div class="trow"><span class="tcell">txt</span></div>
<div class="trow"><span class="tcell">txt sdf sdf</span></div>
<div class="trow"><span class="tcell">txt sdfsdfsdfsdfsd</span></div>
</div>
I have been studying CSS flex recently and was trying out some simple tasks with it. One of these tasks was to make a timeline with alternating elements being above or below a mid-line.
I would like to be able to set an initial width and a fixed height, so that when the content exceeds the height of the div and overflows, the width will expand to accommodate the content, and hopefully there will be no overflow.
https://codepen.io/anon/pen/roVOXB
<div class="content">
<div class="box">
<div class="above">Content of the div</div>
<div class="below"></div>
</div>
<div class="box">
<div class="above"></div>
<div class="below">Content of the div</div>
</div>
<div class="box">
<div class="above">Content of the div</div>
<div class="below"></div>
</div>
<div class="box">
<div class="above"></div>
<div class="below">Content of the div</div>
</div>
<div class="box">
<div class="above">Content of the div</div>
<div class="below"></div>
</div>
</div>
.content {
display: flex;
}
.box {
display: flex;
flex-direction: column;
}
.above, .below {
height: 350px;
display: flex;
min-width: 300px;
border: 1px solid #000;
}
.above {
display: flex;
align-items: flex-end;
background: orange;
}
.below {
display: flex;
align-items: flex-start;
background: aqua;
}
I know it might be a simple solution and its staring me right in the face, but I have tried everything with max-widths, max-heights, overflows and wrapping the text but nothing can help me achieve the desired outcome so far.
I would really appreciate any help. Thanks!
You can change the elements dynamically using the following JS:
var allElements = document.querySelectorAll('.below, .above');
allElements.forEach((Ele) => {
if(Ele.scrollHeight > 350){
Ele.style.minWidth = (Ele.scrollHeight) + "px";
}
});
What is does it iterate through all the elements with classes below and above, then checks if it uses more height than the height: 350px, if it is > 350px, then it will adjust accordingly.
Just add the above JS code in your codepen JS editor, and you're good to go. Try adding more content to it and it will dynamically change the width w/o overflow.
If the number of columns is static, you can remove the min-width from .above, .below.
Add min-width: 2700px; to .content.