Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

CSSOM Viewport

Chapter 53 16 mins

Learning outcomes:

  1. What is the viewport
  2. Getting the viewport's dimensions — innerWidth and innerHeight
  3. Scrolling the viewport via scroll() and scrollBy()
  4. Getting the viewport's scroll position — scrollX and scrollY

Introduction

One of the most useful concepts in the CSSOM API is that of the viewport. In this chapter, we'll see what exactly is the viewport and how to obtain its dimensions using the global properties innerWidth and innerHeight.

We'll also consider a couple of global methods to help us change the scroll offset of the window, and retrieve the position of the scroll box via the scrollX and scrollY properties.

What is the viewport?

Let's start with defining the term viewport:

The viewport refers to the viewable region of a webpage in a browser window.

It is the entire region where the web page is rendered. This obviously excludes the menu bars, tool bars, the developer's console panel, and other miscellaneous panels on the browser's window.

Shown below is an illustration of the viewport on different devices:

Viewports on different devices.
Viewports on different devices.

As stated before, the viewport excludes the developer's console panel if if is shown there on the web page. The figure below demonstrates this case:

The viewport excludes the console panel.
The viewport excludes the console panel.

Viewport's dimensions

The viewport's dimensions play a really crucial role in websites. They are used by the rendering engine of the browser when trying to apply CSS styles based on given max-width and max-height screen media.

The viewport's dimensions are used, more or less, to power what we call responsive designing. As we resize the browser window, and with it the viewport as well, different elements on the web page resize themselves accordingly depending on the width/height of the viewport.

Talking about JavaScript specifically, getting the dimensions of the viewport is also useful in the language. For instance, they could be used to execute a piece of code only if the viewport is of a particular size.

In this regard, we are provided with the global innerWidth and innerHeight properties.

innerWidth returns a number denoting the width of the viewport, in pixels, while innerHeight returns a number denoting the height of the viewport.

Consider the following code where we alert the viewport's dimensions in the conventional format width x height:

alert(`${innerWidth}px x ${innerHeight}px`);

Live Example

Try resizing the browser window manually and then refresh the page linked above in order to see the new viewport dimensions.

Scrolling the viewport

The CSSOM API also provides us with a handful of methods to scroll the viewport. They are as follows:

  1. scroll(): scrolls the viewport to a given x and y position.
  2. scrollTo(): alias of scroll().
  3. scrollBy(): scrolls the viewport by a given x and y offset.

Frankly speaking, we'll be able to better understand all of these functions once we learn how to work with events.

scroll() and scrollTo()

The scroll() method, which is as alias of scrollTo(), scrolls the viewport to a given position.

There are two forms of scroll(): one takes two arguments, both numbers; the other one takes one single argument and that an object.

Here's the syntax of the first form:

scroll(x, y)

x and y are both integers, with x specifying the horizontal position of the scroll and y specifying the vertical position of the scroll.

And here's the syntax of the second form:

scroll(options)

options is an object literal with either of the following three properties:

  • left which works similar to the x argument above.
  • top which works similar to y above.
  • behavior which specifies whether the scrolling must be done smoothly (i.e. with an animation) or directly. The two possible values of behavior are 'smooth' and 'auto'. If omitted, 'auto' is the default.

Let's consider some examples.

But before that, let's introduce you very quickly and very briefly to the click event, as the inspecting of scroll() would be intuitive only once we could call it from within the document itself, when asked to.

Obviously another possibility is to go to the console and try out the scroll() function again and again, but this would surely be less intuitive than the former approach where everything has been preprogrammed before and we just need to make a click to execute that.

Anyways, so let's come to the idea of the click event.

The click event

JavaScript is designed around an event-driven model whereby events (i.e. actions) occur and thus get certain pieces of code meant to handle them to be executed. There is a huge collection of events provided to us by JavaScript, when running in the browser runtime environment. One of them, and perhaps also one of the most used, is click.

The click event gets fired on an element node when that element is clicked. For instance, if we click on the button shown below, then a click event would dispatch on it.

Now the way we are able to tap into this very action, when it does occur on the element, is to set up an event handler function on the element.

Fortunately, that's very easy. JavaScript follows a very intuitive convention which is to provide a property on the element node — for each event, starting with the word on followed by the name of the event — that's essentially meant to hold a handler function of that event.

For instance, to handle the click event on an element, we use the onclick property of the element node. Initially, it returns null. However, we could set it to a function in order to handle the click event.

As a very elementary example, below we set up the onclick handler on the <button> element and make an alert when it's clicked.

And this is how to handle the click event on a given element. As we shall see later on in the JavaScript Events unit, this isn't the only way to set up a handler for a given event occuring on a given element — or more better to say, a given target.

There are also some other and, sometimes, better ways to do this. Moreoever there is a lot more to learn about events than is, and could've been otherwise, explored right now.

Alright, given that we now know how to set up a click handler on a given element, it's time that we start exploring the scroll() function.

Consider the following HTML and CSS code:

<button>Bring heading into view</button>
<h1>This is a heading</h1>
body {
   margin: 0;
   height: 2000px;
}
button {
   position: absolute;
   top: 0;
   padding: 15px;
}
h1 {
   margin-top: 1000px;
   background-color: yellow;
   height: 100px;
}

We have a <button> element and a <h1> element which is precisely 1000px far away from the top edge of the page by virtue of the style margin-top: 1000px.

The <body> element's margin is set to 0 to remove the default margin style laid out by user agents; the height: 2000px style is given in order to have a considerably large scrollable area.

Talking about the <button> element, it's positioned absolutely so as to not interfere with the layout of the <h1> element. We want the <h1> element to be precisely 1000px form the top edge of the page, and that's possible only when the button is removed from the normal layout and then a top margin of 1000px is applied to <h1>.

Now in the JavaScript code that follows, we set up a click handler on <button> in order to bring the <h1> element into view, i.e. scroll the viewport such that the <h1> element can be clearly seen:

var buttonElement = document.querySelector('button');

buttonElement.onclick = function() {
   // Bring the <h1> element into view by scrolling the viewport
   // 1000px vertically.
   scroll(0, 1000);
}

Since we know that the <h1> element is exactly 1000px far away from the top edge of the page, we call scroll(0, 1000) (passing 0 as x since we don't want to scroll horizontally) in order to bring it into view.

Let's now execute this code and see the result:

Live Example

Perfect!

Let's consider another example, this time the latter form of scroll() where it accepts an object as argument.

Suppose that we're using the exact same HTML and CSS setup shown above. In the code below, we setup a click handler on <button> to smoothly scroll the <h1> element:

var buttonElement = document.querySelector('button');

buttonElement.onclick = function() {
   // Bring the <h1> element 'smoothly' into view by scrolling the
   // viewport 1000px vertically, 
   scroll({top: 1000, behavior: 'smooth'});
}

Now, let's try executing this code and then see the result.

Live Example

As can be witnessed in the link above, the moment the button is pressed, the <h1> element is brought into view in a nice, smooth animated way.

Technically speaking, smoothly scrolling an element into view isn't only possible via the scroll() (or scrollTo()) function. However, it's for sure that scroll() is a quick way to do it, i.e. just by setting behavior to 'smooth' in the given object.

scrollBy()

There isn't much difference between scroll() and scrollBy() except for that the latter changes the viewport's scroll offset by a given amount.

As for the signature of scrollBy(), it's exactly the same as that of scroll():

scrollBy(x, y)
scrollBy(options)

To review the purpose of each of the parameters listed here, refer to the section above.

To better understand the distinction between scroll() and scrollBy(), suppose that we're currently on the following scroll position: 10px horizontally and 300px vertically. Now, from this point onwards,

  • scroll(0, 500) would take us to the following scroll position: 0px horizontally and 500px vertically. It would literally change the scroll position to the given coordinates.
  • scrollBy(0, 500) would take us to the following scroll position: 10px horizontally and 800px vertically.

In the example below, we demonstrate the function scrollBy().

The following HTML markup sets up a <button> followed by a couple of sections whose sole purpose is to emulate real content on the web page:

<button>Scroll vertically by 100px</button>

<!--The sections below emulate real content on the page.-->
<section>
   <h1>Section 1</h1>
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates adipisci aliquid esse consequuntur dicta ad numquam ea reiciendis, molestiae neque? Explicabo ducimus velit corrupti voluptatum quaerat iste aliquam molestias officiis!<p>
</section>

<section>
   <h1>Section 2</h1>
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illum eaque optio deserunt provident vitae! Omnis eum odio recusandae, inventore iure quia molestias excepturi rem adipisci vero explicabo, sunt blanditiis incidunt? Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ex, praesentium ut perspiciatis deserunt ea sequi molestias debitis, explicabo possimus natus quod nulla maiores soluta, quaerat officia commodi consequatur cupiditate!!<p>
</section>

<section>
   <h1>Section 3</h1>
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates adipisci aliquid esse consequuntur dicta ad numquam ea reiciendis, molestiae neque? Explicabo ducimus velit corrupti voluptatum quaerat iste aliquam molestias officiis!<p>
</section>

The CSS below does two things: firstly, it fixes the button at the top-left corner of the viewport so that it's always there when we need to execute scrollBy(); secondly, it styles the sections in a way that makes them span a large area so as to emulate real content on the page:

button {
   position: fixed;
   top: 0;
   padding: 15px;
}

/* The following CSS simply styles the sections in order to emulate
 real content on the page. */
section {
   height: 400px;
   margin: 100px 0;
   background-color: #ddd;
}

The JavaScript below sets up a click handler on the button element to ultimately invoke scrollBy(), getting the viewport to be scrolled by further 100px vertically, in a smooth transitional manner:

var buttonElement = document.querySelector('button');

buttonElement.onclick = function() {
   scrollBy({top: 100, behavior: 'smooth'});
}

Now, let's see a live view of this example:

Live Example

Simple?

Getting the viewport's scroll position

Apart from getting the dimensions of the viewport, we can also determine the position of its scroll box. Said another way, we can easily determine the scroll position of the viewport.

And that's done with the help of the global properties scrollX and scrollY, which are modern-day aliases of pageXOffset and pageYOffset.

Stating it precisely,

The scrollX property, an alias of pageXOffset, returns back the horizontal scroll position of the viewport.

For instance, if we scroll the page horizontally by 30px from its initial 0px scroll position, scrollX (and pageXOffset) would be equal to 30.

On the same lines,

The scrollY property, an alias of pageYOffset, returns back the vertical scroll position of the viewport.

Note that both scrollX and scrollY are read-only; they can't be set in order to scroll the viewport to a given set of coordinates. To do that, as we saw above, we have the scroll() function.

The example below demonstrates scrollX and scrollY.

Consider the following HTML and CSS :

<button>Alert the current scroll position</button>
body {
   width: 2000px;
   height: 2000px;
}

button {
   position: fixed;
   top: 0;
   left: 0;
   padding: 15px;
}

The <body> element is given a custom width and height in order to allow the page to be scrolled horizontally as well as vertically. In addition to this, we have a fixed button at the top-left corner of the page, which will later on be used to alert the current scroll position of the viewport.

Consider the following JavaScript code where we set up a click handler on the button in order to alert the current scroll position of the viewport via the scrollX and scrollY global properties:

var buttonElement = document.querySelector('button');

buttonElement.onclick = function() {
   alert(`scrollX: ${scrollX}, scrollY: ${scrollY}`);
}

Now, let's try out this example:

Live Example

As we scroll the page horizontally and/or vertically and then click the button, we get the latest scroll position alerted to us, thanks to scrollX and scrollY.