Make an element take up the entire page
Phuoc Nguyen
Posted on January 15, 2024
Sometimes we want users to focus on a specific element that takes up the entire page. For example, when displaying code results, it's helpful to allow users to view the output without any distractions from the implementation details. As you can see, the playground in the original post offers similar functionality.
Another example is when we allow users to click on an image to see it in full-page mode. This has some benefits. First, it allows the user to see the image at its maximum size, which makes it easier to appreciate and examine details that might not be visible otherwise. Second, viewing an image in full-page mode often removes any visual distractions from the surrounding page, allowing the user to focus solely on the image itself. This can be especially useful for images that include text or other important information, as it ensures that the user can see all of the details clearly and without interruption.
In this post, we'll learn how to implement this functionality using JavaScript. Let's dive in!
HTML markup
The layout has two elements: an outer element that we want to view in full page, and an inner element which is a button that triggers the full page view.
<div id="container" class="container">
<button id="view-full-page">Full page</button>
</div>
Viewing in full-page mode
When users click the button, the container element will take up the whole page. To make this happen, we need to handle the click
event of the button.
Inside the handler, we can add the full-page
class to the target element. This class will set the position of the element to fixed and its width and height to 100%, so that it takes up the entire page. We also update the text of the button to say Close when in full-page mode so that users can easily exit out of full-page view.
Here's an example of what full-page
class and the event handler could look like:
.full-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
const containerEle = document.getElementById('container');
const viewFullPageButton = document.getElementById('view-full-page');
viewFullPageButton.addEventListener('click', () => {
containerEle.classList.add('full-page');
viewFullPageButton.innerHTML = 'Close';
});
However, once the target element is in full-page mode, clicking the button should remove the full-page
class and revert the label to its original value.
To make this happen, we need to update the event handler. We can check whether the target element is in full page mode by seeing if it has the full-page
class. If it does, we remove the class and change the button label back to its original text.
Here's an example of what the updated event handler could look like:
viewFullPageButton.addEventListener('click', () => {
const isFullPage = containerEle.classList.contains('full-page');
if (isFullPage) {
containerEle.classList.remove('full-page');
viewFullPageButton.innerHTML = 'Full page';
} else {
containerEle.classList.add('full-page');
viewFullPageButton.innerHTML = 'Close';
}
});
Adding animation to full-page mode
Let's spice up our full-page mode by adding some animation. This will not only make it look cooler but also improve the user experience by clearly indicating that the element is now in full-page mode.
To make this happen, we can use CSS animations. Here's how:
.container {
transition: width 0.3s, height 0.3s;
}
In our case, we're animating the container element as it switches to full-page mode. By transitioning the width
and height
properties over 0.3 seconds, we create a smooth animation that lets users know something has changed on the page.
However, you might notice that the layout breaks as soon as the element changes dimensions. Don't worry, we'll fix this issue in the next section. For now, give the demo a try and see for yourself how adding animation can make a big difference.
Fixing broken layout issue
To fix the layout issue mentioned earlier, we'll create a placeholder that has the same content and position as the original target element. We'll use the cloneElement()
function to create a copy of the target element, ensuring that all the children of the target element are also cloned in the new element. To keep the copied element hidden, we'll set the visibility
property to hidden
. Finally, we'll insert the cloned element right after the original element using the insertAdjacentElement()
function.
const clonedEle = containerEle.cloneNode(true);
clonedEle.removeAttribute('id');
clonedEle.style.visibility = 'hidden';
containerEle.insertAdjacentElement('afterend', clonedEle);
Once the placeholder is in place, we'll animate the original element using JavaScript. Rather than using the CSS animation mentioned earlier, we'll use JavaScript to transition the target element from its original position to a full-page position.
We're going to make a quick change to the .full-page
class by removing the top
and left
properties:
.full-page {
position: fixed;
width: 100%;
height: 100%;
background: #fff;
z-index: 9999;
}
To calculate the original position, we'll use the getBoundingClientRect()
function to determine the bounding rectangle of the target element and retrieve the top
and left
properties from the result.
const rect = containerEle.getBoundingClientRect();
containerEle.style.top = `${rect.top}px`;
containerEle.style.left = `${rect.left}px`;
Now we can animate the target element from its original position to the full-page mode position by calling the animate()
function. This built-in JavaScript method allows us to create animations on HTML elements. We'll define an array with only one element that describes the final state of the animation. The object passed as an argument specifies how long the animation should last and what type of easing should be used.
By setting the fill
property to forwards
, we ensure that the target element retains its final state even after the animation is complete.
This is how we animate the target element:
containerEle.animate([{
top: 0,
left: 0,
}], {
duration: 300,
easing: 'ease-in-out',
fill: 'forwards',
});
Removing the cloned element when exiting full-page mode
When users exit full-page mode, we need to remove any cloned elements that were created and reset the styles for the container element. To accomplish this, we can use the JavaScript Animation API's finish
event, which is triggered when an animation completes its job.
First, we determine the original position of the target element by using the cloned element and then use the animate()
function to animate the target element from the full-page mode back to its original position.
const rect = clonedEle.getBoundingClientRect();
const collapseAnimation = containerEle.animate([{
top: `${rect.top}px`,
left: `${rect.left}px`,
}], {
duration: 300,
easing: 'ease-in-out',
//fill: 'forwards',
});
Once the animation is complete, we handle the finish
event to remove the cloned element and reset any styles applied to indicate the position, such as position
, top
, and left
properties.
Here's an example of how we can handle the finish
event:
collapseAnimation.addEventListener('finish', () => {
clonedEle.remove();
containerEle.style.removeProperty('position');
containerEle.style.removeProperty('top');
containerEle.style.removeProperty('left');
});
By removing the cloned element and resetting the styles for the container element, we can ensure that our page functions as expected and that there are no leftover elements or styles after exiting full-page mode.
Finally, let's check out the latest demo of the steps we've taken so far.
Note
It's important to note that the demo is contained within an iframe, so you may have noticed that the sample code uses the
position: absolute
declaration for the full-page mode. However, in reality, you'll need to change it toposition: fixed
.
See also
It's highly recommended that you visit the original post to play with the interactive demos.
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!
If you want more helpful content like this, feel free to follow me:
Posted on January 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
July 24, 2024