Ensuring the image is properly sized to fit the screen and enabling the default zoom functionality

I am looking to achieve a specific behavior with an image, where it fits the viewport while maintaining its aspect ratio and allowing for zooming similar to how Chrome or Firefox handle local images. Here are the details of my project:

  • The image I have is a large Unsplash image with a ratio of 4896x3264.
  • My goal is to create a "Where Is Waldo" type game where users can zoom in to examine every detail of the image. Initially, I want the image to fit the screen (with the height at 100% maximum). Users should be able to zoom in and out using ctrl + scroll or other shortcuts.
  • This image is displayed in an Angular 9 application within a component's HTML like this:
    <img src="../../assets/img/Background.webp"/>
    And I access this HTML through <router-outlet>.

Currently, when navigating to this page, the image displays in its original size of 4896x3264, which is too tall for a regular screen. Using CSS, I can set the height and width to fit the viewport and center it as follows:

   img {
      max-height: 100%;
      display: block;
    }

However, with this approach, I lose the ability to zoom in on the image to see the details. Even when zoomed to 500%, the image remains fitted on the screen at 1536 x 722.

Opening a local image in browsers like Chrome or Firefox results in the exact behavior I desire: By default (100% zoom), the image fits at 1017x678. Users can zoom to 4896x3264 by clicking on it and gradually zoom in/out using ctrl + scroll. Inspecting the console, I notice that the width and height automatically adjust when zooming in and out:

<img style="-webkit-user-select: none;margin: auto;cursor: zoom-in;"src="file:///D:/Videotec/Background.webp" width="1083" height="722">

Is there a way to replicate this behavior in my application? While I found several topics on fitting images with CSS to the viewport, none seem to address my specific project requirements. If something similar has been discussed before, please let me know as English is not my native language and I may have missed it during my searches.

Screenshot of current behavior: https://ibb.co/DLChrtp

Desired default behavior screenshot: https://ibb.co/p0hLDxn

Thank you in advance for your assistance.

EDIT: I realize my description of the desired behavior may not be comprehensive due to limitations in my vocabulary. Refer to @NVRM's answer for more detailed insights.

EDIT Workaround: Since I couldn't find a pre-built solution, I implemented the desired behavior using Typescript and CSS. My approach involved toggling between classes (one with max-height: 100% and another without any width or height restrictions) based on user actions. Additionally, I had to retrieve click coordinates for centering the view. To ensure the scrolling functionality worked correctly, I leveraged the AfterViewChecked lifecycle hook. I also used a boolean flag for tracking scroll events to prevent unintentional triggers. While I acknowledge this may not be the most elegant solution, it perfectly aligns with the desired behavior for my project.

In .html

<div #videotecContainer class="videotec-container">
  <img
    #videotecImage
    src="../../assets/img/Videotec.webp"
    [ngClass]="zoomed ? 'zoomedIn' : 'zoomedOut'"
    (click)="onClick($event)"
  />
</div>

In .ts:

zoomed: boolean = false;
scrolled: boolean = false;
xPosition: number;
yPosition: number;
@ViewChild("videotecImage", { static: true }) videotecImage: ElementRef;
@ViewChild("videotecContainer", { 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 && this.scrolled) this.scrolled = false;
    this.zoomed = !this.zoomed;
  }

ngAfterViewChecked() {
    if (this.zoomed && !this.scrolled) {
      this.videotecContainer.nativeElement.scrollTo(
        this.xPosition,
        this.yPosition
      );
      this.scrolled = true;
    }

getPixelPositions(event) {
  // Calculate position based on Wolfgang Fahl's answer here: 
  //questions/34867066
}

In .css:

.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;
}

Answer №1

Not quite sure if this is what you're looking for, but essentially, when using a fixed width and background in a div with an absolute unit (like px), the default behavior during zooming is such that the image also gets zoomed?

For a demonstration of this functionality, click on "Full Page".

div {
  height: 100vh;
  background-image: url("https://i.imgur.com/p2dQlq7.jpg");
  background-size: 500px auto;
  background-repeat: no-repeat;
}
<body>
 <div></div>
</body>

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

Tips for designing websites using HTML and CSS

current result: https://i.sstatic.net/eXLPv.png desired output: https://i.sstatic.net/vgl6z.png I am aiming to center the text. add image description here add image description here ...

Fetching images from the web root using asp.net core and React frontend

My current setup consists of an asp.net core web project integrated with React, along with a separate project serving as the API. The API is responsible for saving images to a specific folder named Images in the content root directory. Now, my challenge ...

Set up a global variable for debugging

Looking to include and utilize the function below for debugging purposes: export function debug(string) { if(debugMode) { console.log(`DEBUG: ${string}`) } } However, I am unsure how to create a globally accessible variable like debugMode. Can this be ...

"Discrepancy between default checkbox and its current state

Currently, I am facing a challenge with setting the defaultChecked value of a checkbox to match the value stored in my database. Despite having the correct boolean value in the database, the defaultChecked always ends up being false. Here is how I have ta ...

Center contents of Bootstrap row vertically

I have a simple property grid layout in Bootstrap 3 structured as follows: <div class="row"> <div class="col-md-3"> <div id="propGrid"> <div class="row pgTable"> <div class="col col-md-12"> <d ...

Visual feedback: screen flashes upon clicking to add a class with jQuery

I have successfully added a click event to my pricing tables in order to apply an animation class on mobile devices. However, I am facing an issue where every time I click on a pricing option on my iPhone, the screen flashes before the class is applied. Is ...

React component that enables radio inputs to repeat upon selection

My current project involves creating a quiz app where users can answer single questions using React on Codepen. I am utilizing an API to fetch a question, along with 3 incorrect answers and 1 correct answer, then storing them in the app's state. Howev ...

The touchstart event is activated when you touch an item within

Is it possible to retrieve the index of ul li elements with touchstart, similar to how it can be done with a click function? <ul id = "list" ontouchstart="touchStart(event,'issues')"> <li> ...

Prevent the onClick function of the outer div from being triggered by clicking on the inner div

Similar Question: Stop parent container click event from firing when hyperlink clicked My issue is <div onClick="someJScode();"> ... <div></div> ... </div> I need to prevent someJScode() from executing when the inner di ...

Is the Facebook AJAX Permissions Dialog displayed outside of a Pop-Up?

I have conducted extensive research but have failed to find a clear answer to my query. Although there is plentiful information on Facebook API AJAX/PHP communication, I am unable to locate an example where the Permission Dialog for an app (showPermissionD ...

Executing a Parent Function from a Child Component in Angular 11

I have successfully passed values between Angular components using Input/Output several times before, but I am currently facing a unique situation for which I cannot find a solution: There are two components involved: home.component (parent component) T ...

The OTP submission in Phone Email's phone authentication using Node JS did not result in the reception of the token

I have implemented the “Login with Phone” Button from Phone Email on my Node JS website. The button opens a popup to enter the mobile number and then displays an OTP window after submission. Although I receive the OTP SMS and enter it successfully, I a ...

HTML control for adjusting the pan and tilt of a device

I'm looking to develop an interactive input where users can drag a dot within a box and see the 2D coordinates of that dot displayed. The goal is to use this feature to control pan and tilt values. A similar functionality from another application is s ...

on clicking GTM, obtain a different child element

My HTML code is structured as follows: <div onclick="location.href='https://ford-parts-accessories.myshopify.com/products/ash-cup-coin-holder-with-lighter-element?refSrc=6748959244479&amp;nosto=productpage-nosto-1-fallback-nosto-1';&q ...

Having trouble with ng-click not correctly updating values within ng-repeat

Here is the code snippet: <div ng-repeat="data in products"> <div class=edit ng-click="dataUI.showEdit = true; content = data;"> </div> <div ng-repeat="renew in data.renewed"> <div class=edit ng-click="dataUI ...

Ways to differentiate between a desktop browser width of 1024px and a tablet width of 1024px with the help of jquery

So here's the issue I'm dealing with: I have scroll-based animation functions set up for desktop browsers, and different animations in place for tablet browsers. The challenge is to make these functions work on a desktop with a 1024px dimension. ...

Setting up Angular Universal on an already existing Angular 2 application with the help of the CLI

Encountering obstacles while trying to integrate the universal CLI into an existing Angular 2 application by following the guidelines provided in this link: During the initial command to install angular-universal: npm install body-parser angular2-univers ...

Changing the color of a div element dynamically with JavaScript

Is there a way to improve the code below so that the background color of this div box changes instantly when clicked, without needing to click twice? function updateBackgroundColor(platz_id) { if(document.getElementById(platz_id).style.backgroundCol ...

Is it possible to continuously generate webpages using AJAX?

Is there a way to achieve an infinite scrolling effect in all directions using ajax requests without the need for flash or silverlight? If anyone has an example of this, I would love to see it! Thank you for your time. ...

Can you provide tips on using Ajax to store a cache file?

I've created a javascript/ajax function that retrieves a json file from an external server. The functionality I'm trying to implement includes: Fetching the json file from the external server Saving the json file on the local server Checking if ...