A common mistake when integrating AJAX-ZOOM viewer into a responsive layout is that the parent container misses the height. Browsers calculate the height of an HTML element while building a page. The missing of the calculated height may lead to unexpected results such as the AJAX-ZOOM viewer not showing at all or breaking out of the present layout. This post explains the roots of the issue and suggests several workarounds that are also present within the AJAX-ZOOM example pages.
The main root of the confusion is that a responsive implementation of the AJAX-ZOOM viewer does not have any width or height on its own. Unlike, for example, an image element, the viewer adapts to the parent container and not the other way around. It's like setting the height and width of a child to 100%. The percentage value resolves against the size of the parent container, and if it lacks calculated pixel dimensions, especially the height, the browser is not able to calculate any positive dimensions of the child element.
Usually, the main problem is the indication of the height that leads to a zero calculated height done by a browser. There are barely any issues with the width in practice because HTML elements in which you would insert the viewer mostly have a calculated width despite being empty. In some instances, however, when the width is not defined, and a container is floating or is positioned absolutely or fixed, the width might be missing as well, but this is more seldom. A more common situation that leads to problems with AJAX-ZOOM is that the height of a regular container depends on the contents inside, and therefore it is not set in any way.
As explained earlier, the AJAX-ZOOM viewer tries to adapt to the parent container. Therefore, the parent element's height must be set so that AJAX-ZOOM can read the calculated values and adjust itself accordingly. A missing calculated height may lead to various problems within modern responsive, adaptive, or mixed layouts. In this post, there are several solutions to avoid those problems by preparing the viewer's parent container via CSS or JavaScript.
Before proceeding, it makes sense to define the difference between responsive and adaptive layouts. Compared to detailed and well-elaborated articles, the following definitions may be wrong. However, for the meaning of this topic, they are sufficient.
CSS offers the "@media" queries for this.
For example, on the current page that uses bootstrap CSS, the outer .container
CSS-class is adaptive
but e.g. .col-md-6
column within a .row
is responsive.
example_container_1
is
NaN px.
Located to the left or top of this text, there should be a colored container.
.example_container_1 {
position: relative;
height: 100%;
}
Even though the container's CSS height that is supposed to be the parent container for AJAX-ZOOM is 100%, it is not visible. The container resides within this simplified HTML structure:
<div class="row">
<div class="col-md-6">
<div class="example_container_1" id="example_container_1">
</div>
</div>
<div class="col-md-6">
Text...
</div>
</div>
The height of col-md-6
is not set in any way,
so setting 100% for the container with ID example_container_1
is senseless.
Press on the button below to load the AJAX-ZOOM viewer into this container.
As you can see, as of the recent AJAX-ZOOM version, the viewer loads and is visible! However, the only reason it loads is because AJAX-ZOOM has detected the parent container's missing height and has set it to some pixel value in a cheeky way. Otherwise, it would not be visible at all. That is the reason why some developers decide they need to change an AJAX-ZOOM option or change the core code of AJAX-ZOOM to change that behavior.
Indeed that would be possible. The option that is responsible for the height is
$zoom['config']['picDim']
, but it does not suppose to change the real height of the viewer in a responsive environment.
By the absence of any calculated height, AJAX-ZOOM takes the height value of this option and sets the height of the container.
That makes the viewer neither adaptive nor responsive.
Do NOT try to change the value of the $zoom['config']['picDim']
option to fix this issue.
Also, do NOT try to make it optional by passing a parameter to the config file.
That is the wrong approach!
Rather you should give the parent container a height right away by using CSS or JavaScript.
Anyway, please understand that AJAX-ZOOM sets the parent container's height only in exceptional cases as a last resort. It is doing this by adding the height to the style attribute, which is "strong" in the sense that it overrides rules of a CSS-class defined elsewhere. Additionally to the issues described above, setting a static height may become a problem when the content of the parent container changes, e.g., it changes from standard images to AJAX-ZOOM 360 viewer and back to images again. A likely outcome is that after switching, users end up with a broken layout.
example_container_2
is
NaN px.
The container to the left (or top on narrow screens) has a calculated height. Unlike in the example above, it is visible right away. Press on the button below to load the AJAX-ZOOM viewer into this container.
The HTML structure is the same as in the above example.
<div class="row">
<div class="col-md-6">
<div class="example_container_2" id="example_container_2">
</div>
</div>
<div class="col-md-6">
Text...
</div>
</div>
It has, however, a standard height of 400px.
Additionally, the CSS contains @media
queries.
Depending on the width and height of the viewport, the height changes.
If you go with this solution, you should create your own rules that fit with your layout.
Resize the browser to validate that the size of the parent container changes and the AJAX-ZOOM viewer's size adapts accordingly.
.example_container_2 {
position: relative;
width: 100%;
height: 400px;
}
@media (min-width: 992px) and (min-height: 768px) {
.example_container_2 {
height: 300px;
}
}
@media (min-width: 1023px) and (min-height: 768px) {
.example_container_2 {
height: 450px;
}
}
@media (min-width: 1679px) and (min-height: 992px) {
.example_container_2 {
height: 500px;
}
}
@media (max-height: 480px) {
.example_container_2 {
height: 300px;
}
}
example_container_3
is
NaN px.
As initially differentiated, a responsive element fluidly adjusts its dimensions. The fluid adjustment in this example refers to the height only because this page's layout is adaptive.
.example_container_3 {
position: relative;
width: 100%;
height: 400px;
height: 50vh;
min-height: 300px;
max-height: 545px;
}
Press on the button below to load the AJAX-ZOOM viewer into this container.
Nowadays, the viewport-units
(vw, vh, vmin, vmax
) are widely supported.
The vh
unit means 1/100th of the viewport height.
Other words this is a percentage value relative to the height of the browser's inner-window.
So in the above CSS, the height is 50% of the window height.
The minimal and maximal heights are limited to fixed pixel values, but this is optional.
Of course, you can add @media
queries and finetune the CSS for your layout.
example_container_4
is
NaN px.
You can also use the viewport-units to limit the height responsively. It is convenient not just for the AJAX-ZOOM viewer but even a simple image that should be visible as a whole. The container has a fixed height of 545 pixels, but it is limited to at most 75% of the browser's inner-window height. Resize the browser window to see the effect.
.example_container_4 {
position: relative;
width: 100%;
height: 545px;
max-height: 75vh;
}
Press on the button below to load the AJAX-ZOOM viewer into this container.
Alternatively, there is a possibility to calculate the height with CSS by mixing the viewport-units and pixel values.
max-height: calc(90vh - 70px);
The above means that the container's height should be no larger than 90% of the browser's inner-window height minus 70 pixels. It makes sense if, for example, you have a navigation bar that is always visible at the top of the window, and you want to subtract its fixed height.
example_container_5
is
NaN px.
The above solutions do not keep fixed proportions of the container, which you might want to set depending on your images' aspect ratio.
Bootstrap CSS has .embed-responsive
and .embed-responsive
classes to achieve that.
However, you do not necessarily need to use the entire Bootstrap CSS library for this.
All you need is to define three CSS-classes and create a structure with two nested containers:
<div class="az_embed-responsive az_embed-responsive-test">
<div class="az_embed-responsive-item" id="example_container_5">
</div>
</div>
Press on the button below to load the AJAX-ZOOM viewer into this container. Resize the browser window to confirm that the proportions stay the same.
The CSS for the three classes looks as following:
.az_embed-responsive {
position: relative;
box-sizing: border-box;
width: 100%;
height: 0;
display: block;
padding: 0;
overflow: hidden;
}
.az_embed-responsive-item {
box-sizing: border-box;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.az_embed-responsive-test {
padding-top: 75%;
}
Apparently, it needs an explanation as the height of the .az_embed-responsive
container is set to 0px
.
What happens here is that this outer container has a second CSS class.
We name this class az_embed-responsive-test.
Bootstrap's native classes that correspond to the ".az_embed-responsive-test
" class are,
e.g. .embed-responsive-4by3
, .embed-responsive-1by1
or embed-responsive-21by9
.
The difference between them is only the CSS padding-top
value with a percentage as the unit.
For whatever hardly understandable reason, it creates vertical padding related to the width of the same element.
If you set padding-top to 100%
, you create a square (1 by 1).
If you set padding-top
to 50%
, you create a rectangle with an aspect ratio 2 by 1.
The actual reason is that within the CSS "box model",
a margin or padding specified as a percentage calculates based on the calculated WIDTH of the same element,
and this rule also applies to a vertical margin or padding!
Creating padding, however, does not do the trick alone.
You cannot put your content in this element directly and maintain the aspect ratio because the calculated CSS height is still 0 pixels.
The inner container of .az_embed-responsive
with .az_embed-responsive-item
class does the trick
by being positioned absolutely and having width and height of 100%,
as well as top and left coordinates defined.
Since the .az_embed-responsive
is relatively positioned,
the boundaries of the absolute positioned child container are indicated by the top container.
Also, because it is positioned absolutely, it overlays the padding by breaking out of the layout.
Thus you get a container whereinto you can place something without destroying the aspect ratio.
However, the above does not need to be fully understood for using it.
Just create the nested div elements and set the padding-top to the desired proportion.
Given an aspect ratio of, e.g., 16:9, you can calculate the value as 9/16*100.
That is 56.25%
.
The value can be above 100%.
For portraits, e.g., 9:16, the value is 16/9*100, which is about 177.7778%
.
You could also use the calc CSS function to take into account certain UI elements of the viewer, which are not responsive, e.g.
.az_embed-responsive-test {
padding-top: calc(56.25% + 48px);
}
A significant drawback of this approach is that you cannot responsively limit the height of this composition with standard CSS.
The outer .az_embed-responsive
container still has a calculated height of 0px,
so max-height
can't be applied to it, and unfortunately, there are no CSS properties such as
min-padding
or max-padding
.
Although you can limit the height of the inner .az_embed-responsive-item
container by max-height
CSS value,
it does not reduce the dimensions or, better to say, the room that the outer container claims for itself.
So when the max-height
CSS limitation effectively applies,
you end up with an extensive space below the inner container with the actual content.
The JavaScript solution in the next section fixes this problem.
example_container_6
is
NaN px.
As described in the last paragraph of the previous section, there is no easy way to set a max-height for the containers that preserve an aspect ratio. To achieve this, we have created a simple JavaScript plugin.
The HTML and CSS are the same as in the previous section except that .az_embed-responsive-test
class is not present,
and the outer container with .az_embed-responsive
class has got an ID to differentiate it from other instances on this page.
<div class="az_embed-responsive" id="az_embed-responsive-js">
<div class="az_embed-responsive-item" id="example_container_6">
</div>
</div>
Press on the button below to load the AJAX-ZOOM viewer into this container. Resize the browser window to confirm that the proportions stay the same and decrease when the resulting value of 80% from the height of the window is smaller than the height of the container with the viewer.
Opposingly to the previous solution, the .az_embed-responsive-test
CSS class is redundant, and it is not present in the HTML of this instance
because the padding-top
that creates the proportions is set with JavaScript now!
Limiting the viewer's height makes even more sense for portrait-orientated images, a standard in the fashion niche. When a user deliberately zooms and pans, it is different than when the displayed image is too large and is not visible as a whole on the screen.
Below is the file with the JavaScript plugin that you need to include in your HTML once. It manages the padding of the outer container, and you can set all the limits that were not easily possible to set in previous solutions.
<!-- Helper plugin to deal with embed-responsive class -->
<script type="text/javascript" src="/axZm/extensions/jquery.axZm.embedResponsive.js"></script>
As with any jQuery plugin, the jquery.axZm.embedResponsive
plugin applies to a selector.
Here, the outer container with the id ajaxZoomContainerParent
is the selector.
It is, however, applicable to any other ID or a different selector.
The plugin is part of the AJAX-ZOOM package, so you do not have to download it separately.
<script type="text/javascript">
jQuery("#ajaxZoomContainerParent").axZmEmbedResponsive({
// Aspect ratio e.g. 16:9
ratio: '20:15',
// Defines padding bottom, 100 results in 1:1 proportion
prc: false,
// Limit against the height of the browser window (%)
heightLimit: 80,
// Substract pixel value from heightLimit
deduct: 20,
// Minimal height of the container
minHeight: 150,
// Override options depending on window width
maxWidthArr: [
/*
{
maxWidth: 768,
ratio: '1:1',
prc: false,
heightLimit: 80,
deduct: 20,
minHeight: 150,
}
*/
]
});
</script>
The options ratio
and prc
are just alternative ways to define the proportions of the container.
You can choose between the two options.
To the maxWidthArr
option, which is an array, you can add objects containing the same main options.
The extra maxWidth
option in each of the objects defines the breakpoints.
It is the equivalent of using e.g. the @media (max-height: 768px)
in CSS
meaning that you can override CSS values depending on the width of the viewport of the browser's window.
You can apply jQuery.axZmEmbedResponsive
to a container more than once without previously destroying it.
The plugin does it automatically, and even when AJAX-ZOOM viewer is already present in the inner container,
it adjusts to the new dimensions automatically as well.
To use live-support-chat, you need to have Skype installed on your device. In case live support over Skype is not available immediately, please leave us a message or send an email by using the contact form.
We answer every inquiry or question that relates to the AJAX-ZOOM software!
Vielen dank!
-- Yermo