Arrange the content of mat cards including images, text, and buttons in a neat alignment

I am currently working on implementing the mat-card in a list, but I'm facing alignment issues.

This is the current layout:

https://i.sstatic.net/VvLRH.png

Here is the desired layout:

https://i.sstatic.net/iGO5o.png

The code snippet is as follows:

<div class="margin-top-20" fxFlexFill fxLayout="row wrap" fxLayout.xs="column" fxLayout.sm="column" fxLayoutGap="15px grid">
  <div fxFlex="20" fxFlex.md="33" *ngFor="let advert of adverts; let i = index" class="padding-fix">
    <div fxFlexFill fxLayoutAlign="center stretch">
      <mat-card class="ad">
        <div fxLayoutAlign="space-between center">
          <img mat-card-image src="test" alt="test">
        </div>
        <mat-card-title>test</mat-card-title>
        <mat-card-content>
          <p>
            test
          </p>
        </mat-card-content>
        <mat-card-actions align="end">
        </mat-card-actions>
      </mat-card>
    </div>
  </div>
</div>

I need help with aligning and resizing the image within each card element.

UPDATE: With the assistance from coreuter, I made progress towards achieving the desired layout.

https://i.sstatic.net/TbmeF.jpg

However, there are still some issues such as uneven heights of the blocks and blank spaces at the end of each row (aiming for 5 elements per row).

Here is the revised code:

...

Answer №1

I previously answered your SO question, so I will use that as a reference for my response to this question. You can view the updated Stackblitz with images of varying widths and heights.

https://i.sstatic.net/EqXvf.png

EDIT: I have made adjustments to the answer and Stackblitz to display 5 elements in a row.

Explanation

To maintain consistent image height, I added the "image" class to the <img> tag (you could also apply the CSS directly to the img tag using .product img{...}).

<img class="image" mat-card-image src="{{product.picture.url}}" alt="photo">

I then applied the following CSS:

.image{
  height: 150px; /* adjust as needed */
  object-fit: contain;
}

By using object-fit: contain, the image will always be properly scaled and fully visible within the available area.

Note that object-fit is currently only fully supported by certain browsers.

EDIT:

To achieve 5 elements in each row, you need to adjust the fxLayoutGap and calculate the width for each element using the fxFlex attribute. Modify your code as follows:

<div class="container" fxLayout="row wrap" fxLayoutAlign="center center" fxLayoutGap="20px">

    <!-- Add addProduct-button outside loop -->
    <mat-card fxFlex="0 1 calc(20% - 20px)" (click)="addProduct()" class="product">
     ...
    </mat-card>

        <!-- loop over the products -->
    <mat-card fxFlex="0 1 calc(20% - 20px)" *ngFor="let product of products; let i = index" class="product">
      ...
    </mat-card>

</div>

Adjust the value of 20px set on the fxLayoutGap and within the calculation of fxFlex based on your preferences.

With these values set, remember to apply a min-width value to prevent all elements from becoming smaller in width without wrapping:

.product{
  min-width: 180px; /* adjust as desired */
  min-height: 250px;
  margin-bottom: 20px; /* same as fxLayoutGap for even distribution */
}

EDIT 2

To ensure the first element matches the height of the others, adjust the (min-)height properties of the .product CSS-class to match the tallest product's height.

EDIT 3 (to address edit 2 of the question)

Since your question hasn't been marked as answered yet, I have modified the code provided in your edit #2 to achieve your desired design: stackblitz

Changes made include:

  • Updated the fxLayoutAlign on the container to "space-evenly stretch" instead of fxLayoutAlign="start start" for even distribution and consistent height.
  • Removed all instances of fxFlexFill
  • Added fxFlex to the mat-card-content
  • Removed the height property from the .product CSS-class

If there is an issue with the border on the left side, it may be due to the container being too close to the left edge of the browser window. I have adjusted the container CSS in the stackblitz as well.

Answer №2

.advertisement{
 display:flex;
 flex-direction:column;
 height:100%;
}
img,mat-card-content{
flex-grow: 1;
}
mat-card-actions{
display: inline-block;
align-self: flex-end;
}

Feel free to give this a shot.

Answer №3

When working with the mat-card, it is important to use fixed sizes and ensure that the images fit within the available space.

.margin-top-20>div>div {
  display: flex;
  width: 100%;
}

.ad {
  width: 200px;
  height: 250px;
  min-height: 250px;
  max-width: 200px;
  border: thin solid #eee;
}

.ad>div {
  width: 100%;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.ad>div>img {
  flex: 0 1;
  width: 100%;
  height: auto;
}
<div class="margin-top-20" fxFlexFill fxLayout="row wrap" fxLayout.xs="column" fxLayout.sm="column" fxLayoutGap="15px grid">
  <div fxFlex="20" fxFlex.md="33" *ngFor="let advert of adverts; let i = index" class="padding-fix">
    <div fxFlexFill fxLayoutAlign="center stretch">
      <mat-card class="ad">
        <div fxLayoutAlign="space-between center">
          <img mat-card-image src="https://via.placeholder.com/150x50" alt="test">
        </div>
        <mat-card-title>test</mat-card-title>
        <mat-card-content>
          <p>
            test
          </p>
        </mat-card-content>
        <mat-card-actions align="end">
        </mat-card-actions>
      </mat-card>
      <mat-card class="ad">
        <div fxLayoutAlign="space-between center">
          <img mat-card-image src="https://via.placeholder.com/50x150" alt="test">
        </div>
        <mat-card-title>test</mat-card-title>
        <mat-card-content>
          <p>
            test
          </p>
        </mat-card-content>
        <mat-card-actions align="end">
        </mat-card-actions>
      </mat-card>
      <mat-card class="ad">
        <div fxLayoutAlign="space-between center">
          <img mat-card-image src="https://via.placeholder.com/350x150" alt="test">
        </div>
        <mat-card-title>test</mat-card-title>
        <mat-card-content>
          <p>
            test
          </p>
        </mat-card-content>
        <mat-card-actions align="end">
        </mat-card-actions>
      </mat-card>
    </div>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is a table cell's border considered as part of its content?

A discrepancy is observed in the rendering of a document on Firefox and Chrome browsers: <!DOCTYPE html> <html> <head> <title>Testing table rendering</title> <style> table { ...

Determine to which observable in the list the error corresponds

const obs1$ = this.service.getAllItems(); const obs2$ = this.service.getItemById(1); combineLatest([obs1$, obs2$]) .subscribe(pair => { const items = pair[0]; const item = pair[1]; // perform actions }, err => { // det ...

Ways to retrieve the ngValue from various select elements created in the HTML code

I'm dealing with a JSON list of roles that includes their id, name, and parent_id (referring to themselves). roles My goal is to display all the roles along with their names and corresponding parents. The parent will be displayed in a select input, ...

Do you have to change the style of each individual element using JavaScript, or is there another method to accomplish this?

Recently, I've been exploring different ways to use JavaScript to globally adjust styles. My goal is to modify the CSS rule that controls the element's style, similar to how you can do it using the Inspector in Webkit. However, after visiting htt ...

Angular project is missing both links and labels from dagre-d3 visualization

I've been working on integrating dagre-d3 with Angular, but I've hit a roadblock. Challenges: The links between nodes are not showing up. The labels on the nodes are not being displayed. Visit this link for reference I&ap ...

Default Slider Features

I am in need of assistance to create a slider similar to this example. Can anyone help me with this? <link type="text/css" href="ui.all.css" rel="stylesheet" /> <script type="text/javascript" src="jquery-1.3.2.js"></script> <script ...

The OnPrepareResponse method in StaticFileOptions does not trigger when serving the index.html file

Currently, I am attempting to disable caching for index.html in my Angular SPA that is connected to a .NET Core 2.2 backend. I am following the instructions provided in this particular answer by implementing an OnPrepareResponse action for my StaticFileOp ...

bsDatepicker restricts the selection of dates after the endDate

I'm attempting to set the minDate for endDate inputs to be one day after startDate's value. Can anyone spot what I'm doing wrong? Check out stackblitz .ts this.minendDate.setDate(this.minendDate.getDate() + 1); this.maxendDate.setDate(this ...

Unable to adjust the main-container height in Bootstrap to 100%

I'm struggling to set the height of my .main-container to 100%. When I try to do that, the height ends up being too high. Here is a screenshot for reference: enter image description here .main-container { height: 94vh; } Here is some of my code ...

Implementing the switchClass function on a parent class when hovering over a child class, while ensuring that only the specific divs are targeted and not others with the

Currently using the .switchClass function on both the .container divs whenever I hover, causing all child1 elements within these containers to change from 100% width to 40% width. However, I only want this switch to occur on the specific container that I&a ...

If I deselect an item, the "check all" option does not become deselected

I recently designed a page that displays all the weekdays and dates from Monday to Sunday. I added a feature where users can check all the weekdays with a single click, and uncheck them with another click. However, I encountered an issue where unchecking a ...

Switching the visibility of a DIV by clicking on a list item

Struggling with a seemingly simple function for way too long now. The task is to show a hidden div with information on an item when it's clicked, without using jQuery. Tried multiple examples from various sources but nothing seems to work. Hoping for ...

What are the best strategies to prevent text from appearing jumpy while fading in word by word?

I'm struggling to create a smooth fade-in effect word by word without causing the first word to suddenly jump to the left when the second word appears. To better explain my issue, I've provided a jsfiddle link: http://jsfiddle.net/6czap/504/ If ...

What could be causing my CSS code to not function properly within Vue.js?

Having trouble with css in VueJs. I can't seem to figure out what I'm doing wrong. Generally, my scoped style css works fine in vuejs, I can target ids and classes without any issues. The problem arises when trying to change the internal css va ...

Nested tables in CSS

Creating a Gridview with two nested Gridviews in separate cells may result in some CSS inheritance issues. Each row of the table contains these nested Gridviews, but trying to isolate their style using CssClass doesn't always work effectively. Is the ...

Clicking with jQuery to float left and then bringing back

I have written this JavaScript code that is supposed to float the address div to the center when you click on the info panel using the "addressmoved" class. Challenges However, when I click on the trigger button, instead of the address div moving to the ...

The impressive wipe effect in velocity.js using css and jquery

I am looking to achieve a slide effect similar to Powerpoint's wipe using css, jquery, or velocity.js. Here is a video showing the desired effect: https://www.youtube.com/watch?v=VSBB0wfccws I attempted to use css3 masking (svg/gradient) but was uns ...

Troubleshooting: When Angular Fade In Out Animation Won't Work

Looking to create a simple animation with the angular animation package The goal is to smoothly transition from opacity 0 to opacity 1 for a fade effect. I've had success with other properties like height and display, but struggling with opacity. H ...

Replace the content of the HTML tag in the index.html file with a different HTML file located at a specific URL in an Angular application

Currently utilizing angular universal. The primary URL being: Upon opening this URL, the function res.render('index') is triggered, leading to the rendering of the index.html file, as depicted in the following code snippet. app.get('*' ...

Tips for sending asynchronous data to Google-Charts-Angular

I am currently working on generating a chart using data obtained from an API call. To achieve this, I am utilizing the google-charts-angular package within my HTML: <google-chart [title]="title" [type]="type" [data]="data" ...