DEV Community

Cover image for Hacks I've Learned in Developing Interactive Web Pages
Naufan Rusyda Faikar
Naufan Rusyda Faikar

Posted on • Edited on

Hacks I've Learned in Developing Interactive Web Pages

During the development of several interactive web pages, I have learnt a lot. Here are some interesting findings.

Scroll Bar's Height

Sometimes when we have:

#title {
    position: absolute;
    left: 0;
    bottom: 0;
}
Enter fullscreen mode Exit fullscreen mode

to prevent the browser' scroll bar from covering our web page's content;

Overlapping scrollbars

we need to subtract the page' size by the scroll bar's width;

const scrollBarWidth = () => {
    let inner = document.createElement('p');
    inner.style.width = "100%";
    inner.style.height = "200px";

    let outer = document.createElement('div');
    outer.style.position = "absolute";
    outer.style.top = "0px";
    outer.style.left = "0px";
    outer.style.visibility = "hidden";
    outer.style.width = "200px";
    outer.style.height = "150px";
    outer.style.overflow = "hidden";
    outer.appendChild(inner);

    document.body.appendChild(outer);
    let w1 = inner.offsetWidth;
    outer.style.overflow = 'scroll';
    let w2 = inner.offsetWidth;
    if (w1 == w2) w2 = outer.clientWidth;
    document.body.removeChild(outer);

    return (w1 - w2);
};
Enter fullscreen mode Exit fullscreen mode

So, it will looks like:

Non-overlapping scrollbars

Credit to http://www.alexandre-gomes.com/?p=115.

Dynamic Viewport Height

To fit elements to the height of the viewport, we often think to set the height to 100vh. Unfortunately, this will contribute to a headache when we target mobile devices, because we often see the address bar disappear when scrolling. Until all major browsers support dv* units, we can create our own scale units. In CSS:

#main-container {
    height: calc(var(--dvh, 1vh) * 100);
}
Enter fullscreen mode Exit fullscreen mode

In JavaScript:

let dvh = window.innerHeight * 0.01;
document.documentElement.style.setProperty("--dvh", dvh + "px");
Enter fullscreen mode Exit fullscreen mode

This technique will become more of use when dealing with elements with a defined aspect ratio. Consider we have this on iPad:

Game canvas on iPad

We can set, for example, the font size as:

.title {
    font-size: calc(var(--dvh, 1vh) * 15);
}
Enter fullscreen mode Exit fullscreen mode

But on iPhone, we have this instead:

Game canvas on iPhone

The font size will not scale as expected. To get rid of this situation, we can do as follow. In CSS:

.title {
    font-size: calc(var(--dch, 1vh) * 15);
}
Enter fullscreen mode Exit fullscreen mode

In JavaScript:

// Resize the container to fit the screen
let mainContainer = document.getElementById("main-container");
...

// Create a custom unit
let dch = mainContainer.style.height * 0.01;
document.documentElement.style.setProperty("--dch", dch + "px");
Enter fullscreen mode Exit fullscreen mode

So, it will looks like:

New game canvas on iPhone

Credit to https://css-tricks.com/the-trick-to-viewport-units-on-mobile/.

Specific Browser Identification

As good web developers, we must ensure that our web pages look equally correct—not necessarily to be precisely the same—on every target browser running on different operating systems. Sadly, we got this:

Font Rendering on Chrome vs Firefox

with CSS as below:

#start-button {
    padding: calc(var(--canvasHeight, 1vh) * 0.75) 0;
    padding-bottom: calc(var(--canvasHeight, 1vh) * 1.0);
    font-size: calc(var(--canvasHeight, 1vh) * 8);
    ...
}
Enter fullscreen mode Exit fullscreen mode

Let us take a closer look. In Chrome:

Font Rendering on Chrome

In Firefox:

Font Rendering on Firefox

See? I guess, this is related with this "bug".

Someone may have found a better solution, but I would think that I need to apply separate styles with duck-typing technique for Chrome and the others.

For example, we could add:

/*
 * Chrome-only CSS hacks
 **/
@supports (not (-webkit-hyphens: none)) and (not (-moz-appearance: none)) and (list-style-type:"*") {
  #start-button {
      padding-bottom: calc(var(--canvasHeight, 1vh) * 2.0);
  }
}
Enter fullscreen mode Exit fullscreen mode

So that it can looks as:

Hacked Button Style on Chrome vs Firefox

Let us zoom in a little:

Hacked Button Style on Chrome vs Firefox

Perfect!

Credit to https://browserstrangeness.github.io/css_hacks.html. Please go to the page to find out more.

In rare cases, we may also want to make our web pages work in other browsers such as Samsung Internet and UC Browser, as they both have accordingly 3% and 1.5% market share in our country. But the previous reference does not include those browsers. In this case, we could have to put this in CSS:

/*
 * UC Browser-only CSS hacks
 **/
html[data-useragent*='UCBrowser'] #start-button {
    padding-bottom: calc(var(--canvasHeight, 1vh) * 2.0);
}
Enter fullscreen mode Exit fullscreen mode

In JavaScript:

var root = document.documentElement;
root.setAttribute('data-useragent', navigator.userAgent);
root.setAttribute('data-platform', navigator.platform );
Enter fullscreen mode Exit fullscreen mode

Credit to https://stackoverflow.com/a/29938371/8791891.

Not only the way each browser renders the page, but also how they implement things. I had several Safari-specific issues like the ended media event not firing and there is audio playback delay. It made me thinking to identify the browser with another duck-typing technique, similar to:

const isSafari = () => {
    return /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && window['safari'].pushNotification));
}
Enter fullscreen mode Exit fullscreen mode

Credit to https://stackoverflow.com/a/9851769/8791891.

Specific Device Identification

In other chances, we may want to make a different implementation based on the user's device type. Let us say that we do not want to enable anti-aliasing to the HTML5 canvas on mobile devices. We can have this code:

const isMobileDevice = () => {
    const agent = navigator.userAgent || navigator.vendor || window.opera;
    return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(agent)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(agent.substr(0,4)));
};
Enter fullscreen mode Exit fullscreen mode

Credit to https://stackoverflow.com/a/11381730/8791891

Sometimes, we might find that our web pages do not look the same on desktop and on mobile. Even though they are both Firefox. At this point, we may want to differentiate between the two based on the available media features, combined with the browser detection hack;

/*
 * Firefox on touch input device-only CSS hacks
 **/
@supports selector(:-moz-is-html) {
    @media (any-pointer: coarse) and (not (any-pointer: fine)) {
        #start-button {
            padding-bottom: calc(var(--canvasHeight, 1vh) * 2.0);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Although, well, this is not accurate.

Credit to https://css-tricks.com/interaction-media-features-and-their-potential-for-incorrect-assumptions/.

See you later!

Top comments (0)