title: Fitting image to screen and allow default zoom behavior
body: <p>I want to fit an image to the viewport keeping the aspect ratio and the default zoom behavior of the browser. Basically the wanted behavior is exactly like opening a local image with Chrome or Firefox.
  Here is the detail of my project :</p>
  <ul>
  <li>I have a huge Unsplash image of ratio 4896x3264</li>
  <li>I want to create kind of a &quot;Where Is Waldo&quot; game where the user has to zoom in to check every detail of the image. By default I want the image to fit the screen (in this case the height at 100% max). Then the user could zoom in/out with ctrl + scroll (or any other shortcut).</li>
  <li>It is displayed in an angular 9 application, the html of the component simply is :
  <code>&lt;img src=&quot;../../assets/img/Background.webp&quot;/&gt;</code>
  And I access this html with my <code>&lt;router-outlet&gt;</code>.</li>
  </ul>
  <p>So right now when navigating to this page the image is displayed with its original size 4896x3264 which is way too tall for a regular screen. With CSS I can set the height and width to fit the viewport accordingly (and center it) as follow :</p>
  <pre><code>   img {
        max-height: 100%;
        display: block;
      }
  </code></pre>
  <p>However, with this solution I cannot zoom in to see the detail of the image anymore. Even if I zoom to 500% the image will stay fit (on my screen at 1536 x 722).</p>
  <p>When opening the local image in the browser (Chrome or Firefox) I obtain the exact wanted behavior :
  By default (100% zoom) it fits at 1017x678. I can zoom to 4896x3264 by clicking it. And I can gradually zoom with ctrl + scroll.
  When inspecting the console I see that the width and height automatically changes when I zoom in and out :
  <code>&lt;img style=&quot;-webkit-user-select: none;margin: auto;cursor: zoom-in;&quot;src=&quot;file:///D:/Videotec/Background.webp&quot; width=&quot;1083&quot; height=&quot;722&quot;&gt;</code></p>
  <p>Is there a way to get this behavior in my application ? I found a lot of topics on fitting images with css to the viewport but I couldn't find something like my project. As English is not my native language I might have poorly search the web, let me know if something similar has already been addressed.</p>
  <p>Actual behavior screenshot : <a href="https://ibb.co/DLChrtp" rel="nofollow noreferrer">https://ibb.co/DLChrtp</a></p>
  <p>Wanted default behavior screenshot : <a href="https://ibb.co/p0hLDxn" rel="nofollow noreferrer">https://ibb.co/p0hLDxn</a></p>
  <p>Thanks in advance for your help.</p>
  <p><strong>EDIT</strong> :
  I am not sure that I described comprehensively the wanted behavior (my vocabulary limits me). Check @NVRM answer for more details</p>
  <p><strong>EDIT Workaround</strong> :
  As I didn't find something out of the box I recreated the behavior with Typescript + CSS. My idea was simply to toggle ngClass from a responsive class (max-height: 100%) to a raw class with no width and height limitations. As in my game I have to retrieve the exact position of a click I used it also with scrollTo in order to center the view on the wanted coordinates.<br />
  I had to use lifecycleHook AfterViewChecked as I needed to scroll the view after the class was toggled.
  I had to use a scrolled flag (boolean), otherwise the scrollTo(x,y) was also triggered when I clicked to scrollOut.
  I know it is not a clean solution (I actually have more code than below, handling other stuff like dblclick etc. so some part might not seems optimal to you) but it does exactly the wanted behavior so I'll stick to it for now.</p>
  <p>In .html</p>
  <pre><code>&lt;div #videotecContainer class=&quot;videotec-container&quot;&gt;
    &lt;img
      #videotecImage
      src=&quot;../../assets/img/Videotec.webp&quot;
      [ngClass]=&quot;zoomed ? 'zoomedIn' : 'zoomedOut'&quot;
      (click)=&quot;onClick($event)&quot;
    /&gt;
  &lt;/div&gt;
  </code></pre>
  <p>In .ts :</p>
  <pre><code>zoomed: boolean = false;
  scrolled: boolean = false;
  xPosition: number;
  yPosition: number;
  @ViewChild(&quot;videotecImage&quot;, { static: true }) videotecImage: ElementRef;
  @ViewChild(&quot;videotecContainer&quot;, { static: true }) videotecContainer: ElementRef;
  
  onClick(event: any) {
       const coordinates = this.getPixelPositions(event);
       this.xPosition = coordinates.px - coordinates.clientWidth / 2;
       this.yPosition = coordinates.py - coordinates.clientHeight / 2;
       this.zoomImage();
   }
  
  zoomImage() {
      if (this.zoomed &amp;&amp; this.scrolled) this.scrolled = false;
      this.zoomed = !this.zoomed;
    }
  
  ngAfterViewChecked() {
      if (this.zoomed &amp;&amp; !this.scrolled) {
        this.videotecContainer.nativeElement.scrollTo(
          this.xPosition,
          this.yPosition
        );
        this.scrolled = true;
      }
  
  getPixelPositions(event) {
    //do some calculation based on Wolfgang Fahl answer here : 
    //questions/34867066
  }
  </code></pre>
  <p>In .css :</p>
  <pre><code>.zoomedOut {
    max-height: 100%;
    max-width: 100%;
    display: block;
    margin: auto;
  }
  
  .zoomedIn {
    display: block;
  }
  
  #videotecImage {
    overflow: scroll;
  }
     
  .videotec-container {
    height: 100vh;
    overflow: scroll;
    background-color: black;
  }
  </code></pre>