Search code examples
cssangular-materialangular-flex-layout

The cards width is not adjusting to same width size along with only 3 cards in a row


Hello I am trying to adjust the cards in th UI using angular-flex. The width of the cards are responsive as per the text length in it. But I want each card to be of same width irrespective of the content within it.

If I am using max-width, then that is effecting the cards in mobile responsive. Else in responsive view all the card is same size and width.

If I am using display:grid; then the cards are perfect. But I need to do this responsive using flex so I had used display:flex;

This is the UI:-

UI

The HTML :-

<div class="container">
  <div class="cont">
    <app-overview *ngFor="let item of data" [extra]="item.extra" [colorcode]="item.color" [ovrno]="item.value" [ovrtitle]="item.info" >
    </app-overview>
  </div>
</div>

CSS:-

.cont {
  display: flex;
  grid-template-columns: 1fr 1fr 1fr;
  flex-direction: column;
  flex-wrap: wrap;
}

@media (min-width: 900px) {
  .cont {
    flex-direction: row;
    flex-wrap: wrap;
    max-width: 100%;
    margin: auto;
    align-items: stretch;  

}
}
  1. How can I show same card-width irrespective of the content length ?

    PS:- Also, I want to avoid using media query. How can I do the same for different views using flex only ?

  2. Also need to show only 3 cards in a row.

EDIT:-

app-overview component :-

HTML:-

<div class="overview" [ngStyle]="getColor()" (click)="onSelect()">
    <p class="no">{{no}}</p>
    <p class="otitle">{{title}}</p>
</div>

CSS:-

.overview {
  padding: 10px;
  text-align: center;
  border-radius: 10px;
  color: #fff;
  margin: 10px;
  height: 270px;
  cursor: pointer !important;
  .no {
    font-size: 6.5em;
    font-weight: bold;
    padding: 0.3em 0;
  }
  .otitle {
    font-size: 25px !important;
    font-weight: 300;
    padding: 0.3em 0;
  }  
} 

Solution

  • I don't know about no media queries... that's a strange requirement since they're 97.97% supported according to caniuse. But you can do all this with a single media query rule or skip it and have 3 really squished boxes per row.

    On your parent element you only need two rules:

    .cont {
      display: flex;
      flex-wrap: wrap;
    }
    

    And on the children you'll need a little bit of math: The margin (how much distance you need between your cards) plus the horizontal padding inside the cards multiplied by 2 is the final flex value in your larger screen media query, for example:

    .child {
        margin: .5rem; /* This value plus the left to right padding * 2 == final flex value */
        padding: 2rem .25rem; /* Padding given for example on inner element */  
        flex: 100%;
        display: flex;
    }
    
    @media (min-width: 640px) { /* Or whatever breakpoint makes your content not look janky */
        .child {
            flex: 0 1 calc(33.33333% - 1.5rem); /* (.5 + .25)*2 = 1.5rem this is the final flex value */
        }
    }
    

    Why this works well: On smaller screens (the default) setting flex: 100% is the equivalent of setting flex-basis to 100% (since we're providing a unit) which fills the width when we want to stack elements.

    On larger screens the flex-basis (last number in flex property) is being explicitly set as 1/3 of the screen width minus the sum of the horizontal margin and padding of the element inside the container which forces each one to take up 1/3 of the screen, while the flex-grow (first number in the flex property) is being set to 0 otherwise the rows with less than three will grow to share the space available.

    Here's a working example I made with Svelte based on your image but the concept of the CSS is identical so it shouldn't matter what framework you're using.