adam0101
adam0101

Reputation: 30995

Image stretches to 100% while loading when server-side rendering

I have the following code which uses Angular Material to make my image responsive:

<picture [ngStyle.xs]="{'width': '100%'}" [ngStyle.gt-xs]="{'width': '448px', 'height': '60px'}">
  <source srcset="/assets/images/logo-text-lg.webp" type="image/webp" [ngStyle.xs]="{'width': '100%'}" [ngStyle.gt-xs]="{'width': '448px', 'height': '60px'}">
  <source srcset="/assets/images/logo-text-lg.png" type="image/png" [ngStyle.xs]="{'width': '100%'}" [ngStyle.gt-xs]="{'width': '448px', 'height': '60px'}">
  <img src="/assets/images/logo-text-lg.png" alt="TechScore" [ngStyle.xs]="{'width': '100%'}" [ngStyle.gt-xs]="{'width': '448px', 'height': '60px'}">
</picture>

The goal is to have it exactly 448x60 unless it is on an extra small screen. Then it should be 100% of the page width. This works except that, since I implemented server-side rendering via Angular Universal, I get a flash of the image at 100% even on larger screens.

stretched image

image once loaded

If I look at the source (with caching disabled) I can see that the markup coming from the server includes style="width: 100%" which means that the server-side rendered version thinks that the screen is extra small.

How can I let Angular Universal known what the screen resolution is and how do I pass that information on to Angular Material and override what it thinks is the resolution so that it chooses the correct width?

Update

I thought I was onto something by detecting if it was a mobile browser via the user-agent string and then setting the default breakpoints as described here: https://github.com/angular/flex-layout/wiki/Using-SSR-with-Flex-Layout

FlexLayoutModule.withConfig({ssrObserveBreakpoints: [isMobile() ? 'xs' : 'md']})

but I must be doing it wrong because I'm not seeing any effect.

Upvotes: 8

Views: 1635

Answers (5)

Simon_Weaver
Simon_Weaver

Reputation: 145890

FlexLayout does support server side rendering with certain limitations.

I wouldn't attempt to use it without first reading this document

Angular Flex Layout - Server Side Rendering

Upvotes: 0

Deeksha gupta
Deeksha gupta

Reputation: 659

Please try CSS below this will maintain the ratio.

 .img-fluid {
    max-width: 100%;
    height: auto;
     }

Upvotes: 0

Love Pandey
Love Pandey

Reputation: 330

If You want to keep same size throughout the site. Than it may help you.

 <picture>
          <source srcset="/assets/images/logo-text-lg.webp" class="my-picture" type="image/webp">
          <source srcset="/assets/images/logo-text-lg.png" class="my-picture" type="image/png" >
          <img src="/assets/images/logo-text-lg.png" class="my-picture" alt="TechScore">
 </picture>

<style>
        .my-picture {
          width: 448px;
          height: 60px;
        }

        @media only screen and (max-width : 480px) {
          .my-picture {
            width: 100%;
            height: auto;
          }
        }

       @media only screen and (max-width : 667px) {
          .my-picture {
            width: 50%;
            height: auto;
          }
        }

       @media only screen and (min-width : 668px) {
          .my-picture {
            width: 448px;
           height: 60px;
          }
        }

</style>

You may change size according to your requirements.

Upvotes: -2

KLTR
KLTR

Reputation: 1334

You can set a variable inside your Typescript that states if the screen is in mobile (by width) and then change the classes.

here's an example :

isMobile = false;
ngOnInit() {
    if (window.screen.width <= 480) { // 768px portrait
      this.isMobile = true;
    }
}

then inside your template :

<picture [ngClass.xs] = "isMobile">
 ...
</picture>

Edit:

I saw you were looking to get the screen size into the server. There is no way for the server to get the screen size unless you send him this data, and save it. You can send the window.screen.width into the server when the client starts and then serves the specific user with the screen size you have.

Upvotes: -1

Tom Faltesek
Tom Faltesek

Reputation: 2818

You could consider using CSS media queries to handle the responsive styling of the images. Then no hardcoded inline styles will be sent to the client. The browser will determine how to initially render the images. You won't have to wait for your JavaScript to execute (flash!) before the appropriate styles are applied.

Here's an example:

<picture class="my-picture">
  <source srcset="/assets/images/logo-text-lg.webp" type="image/webp">
  <source srcset="/assets/images/logo-text-lg.png" type="image/png" >
  <img src="/assets/images/logo-text-lg.png" alt="TechScore">
</picture>
.my-picture, .my-picture img, .my-picture source {
  width: 448px;
  height: 60px;
}

@media only screen and (min-width : 480px) {
  .my-picture, .my-picture img, .my-picture source {
    width: 100%;
    height: auto;
  }
}

Upvotes: 5

Related Questions