Have you ever come throughout a problem the place there’s a mounted ingredient on cellular, and when the keyboard is activated, that ingredient can be hidden beneath the keyboard?
This has been a default conduct on the net for years. On this article, we’ll discover the issue, why it occurs, and the way we will remedy it right now with the digital keyboard API.
Let’s dive in.
The issue
Earlier than diving into the fantastic particulars, allow us to stroll by means of an instance. This can be a UI that has the next:
- Sticky header
- Sticky floating motion button (FAB)
When the consumer focuses on the enter, the digital keyboard will present. Are you able to anticipate what is going to occur?
The browser will scroll upwards to make the enter above the keyboard, and thus the sticky header and floating button will disappear.
It seems just like the next:
This can be a default conduct in cellular browsers typically. From a UX perspective, it could be annoying to cover components of the UI, particularly these components which might be associated to the present motion I’m doing whereas the keyboard is energetic.
Behind the scenes, what occurs is one thing just like the next determine.
In technical phrases, the seen half is known as the visible viewport, and the hidden components together with what’s presently seen is the format viewport.
The primary downside is that the visible viewport shrinks in dimension when the digital keyboard is energetic.
Repair content material hidden underneath the keyboard with the digital keyboard API
Because of the digital keyboard API, we will outline that each the visible and format viewports are equal. With that, we will detect the keyboard place and dimensions with the next CSS setting variables:
- keyboard-inset-top
- keyboard-inset-right
- keyboard-inset-bottom
- keyboard-inset-left
- keyboard-inset-width
- keyboard-inset-height
By utilizing the above variables, we will alter a format when the digital keyboard is energetic.
Browser assist
On the time of writing this text, the VirtualKeyboard API is supported solely in Chrome for Android.
Within the subsequent part, I’ll discover just a few examples and use-cases the place it may be useful.
Enabling the digital keyboard API
This API isn’t out there by default. We have to use Javascript to allow it.
See the next:
if ("virtualKeyboard" in navigator) {
navigator.virtualKeyboard.overlaysContent = true
}
I discovered this a bit bizarre; utilizing Javascript to allow such conduct. I agree with Bramus in his article in regards to the subject. He recommended utilizing a meta tag like this:
<meta
title="viewport"
content material="width=device-width, initial-scale=1.0, virtual-keyboard=overlays-content"
/>
Or CSS property:
html {
virtual-keyboard: overlays-content;
}
Replace: 2 Aug 2023
Bramus kindly famous that there’s a new interactive-widget
within the viewport meta tag which helps in altering the resizing conduct.
See MDN for particulars.
Use instances for the VirtualKeyboard API
Backside-fixed actions
On a smaller viewport, you would possibly have to have a name to motion button or footer that’s mounted to the underside of the UI.
Think about the next determine the place we’ve a CTA button that’s mounted to the underside. In the midst of the display, there may be an enter area.
When the enter area is energetic, the checkout button can be underneath the digital keyboard, thus it’s hidden.
We are able to repair that simply with the digital keyboard API.
enter {
font-size: 16px;
}
.cta {
backside: env(keyboard-inset-height, 0);
}
On cellular, the worth of backside
can be equal to the keyboard top, thus offsetting the CTA button with that worth. If the browser doesn’t assist the API, it is going to default to zero.
You could be questioning in regards to the lowered area as a result of presence of the header and stuck backside. We are able to use vertical media queries to point out the header if the vertical area is sufficient.
Scrolling to the very finish of the web page isn’t doable
When there may be an merchandise with place: mounted
on the very backside of the format viewport, we often add a padding-bottom
to offset the web page and permit the consumer to scroll to the very finish.
physique {
--cta-height: 60px;
padding-bottom: var(--cta-height);
}
.cta {
backside: env(keyboard-inset-height, 0);
}
The padding-bottom
must be a worth that is the same as or higher than the mounted ingredient top.
Cool, proper? What occurs once we contain a digital keyboard? Let’s have a look.
Think about the next determine:
When the digital keyboard is energetic, the padding-bottom
worth with the peak of the mounted ingredient isn’t sufficient. We have to add a keyboard to it.
To visualise the difficulty higher, here’s a video:
To repair that, we have to detect when the enter is concentrated and alter the padding-bottom
primarily based on that.
physique:has(enter:focus) {
padding-bottom: calc(
var(--cta-height) + env(keyboard-inset-height, 0)
);
}
You would possibly surprise, what is going to occur on desktop? Good query. The env()
will fall again to 0
and the entire will outcome within the worth of var(--cta-height)
.
Floating motion button
On this instance, we’ve a floating motion button that’s positioned on the backside proper nook of the web page.
When the keyboard is energetic, the floating button ought to transfer above it. As within the very first instance, the floating button can be underneath the keyboard.
To repair that, we will use the env(keyboard-inset-height)
worth.
Let’s stroll by means of the answer:
.fab {
backside: calc(1rem + env(keyboard-inset-height, 0rem));
}
I used 1rem
plus the keyboard top, to keep away from having the floating button immediately on the prime fringe of the keyboard.
With CSS comparability features, it’s vital to notice that utilizing a unitless quantity for the fallback worth inside the env()
will break the entire thing in Safari. We should add the unit rem
.
Utilizing a unique worth for desktop
Suppose that we wish to offset the floating button a bit extra on desktop browsers, how we will try this? Nicely, I considered utilizing the max()
comparability operate, and it labored.
.fab {
backside: max(2rem, 1rem + env(keyboard-inset-height, 0rem));
}
Right here is the way it works:
- The comparability operate will examine between the 2 values. Because the
env(keyboard-inset-height)
evaluates tozero
on desktop, the utmost worth is2rem
. - On cellular, the utmost worth is the second.
To study extra about CSS comparability features, you may learn this text.
Chat format
I received impressed by the instance in this text by Thomas Steiner and wished to point out you the way it works.
Think about the next determine:
When the keyboard is energetic, each the header and the message area are hidden. We are able to use the env(keyboard-inset-height)
as a worth for the grid-row
property.
.format {
show: grid;
grid-template-rows: auto minmax(0, 1fr) auto env(keyboard-inset-height, 0);
top: 100dvh;
}
Right here is the way it seems with the repair above:
Use the digital keyboard API properly
The digital keyboard must be used solely when wanted. Utilizing it in every context would possibly trigger issues. Sure, you learn that proper.
Let’s take a easy instance. We’ve a contact web page with lengthy content material and kind inputs. If we opt-in for making the digital keyboard overlaying the web page’s content material, it gained’t be doable to scroll to the very finish of the shape.
On this case, I don’t advocate having the keyboard overlay the content material. Use it properly.
See the next video to get a sense of the issue:
Utilizing the comparability features with the digital keyboard API
Morphing a button primarily based on the visibility of the digital keyboard
This could be a ineffective use case or an instance, but it surely’s attention-grabbing to see what occurs when a function is used to its full potential.
I assumed to myself, why not combine CSS comparability features and the digital keyboard env
values? I did that, and it labored.
See the video under:
How does that work? Right here you go:
.fab {
--size: 4rem;
place: mounted;
proper: min(1rem, 100vw - env(keyboard-inset-width, 0rem));
backside: max(1rem, env(keyboard-inset-height, 0rem));
width: max(var(--size), env(keyboard-inset-width, 0rem));
top: var(--size);
border-radius: max(
0px,
min(50px, 100% - env(keyboard-inset-width))
);
}
This works on each desktop and cellular. Here’s what’s occurring:
- The
proper
worth can be both1rem
orzero
. The primary is for desktop, and the latter is for cellular (when the keyboard is energetic).100vw
is the same as the keyboard width in that case, thus the end result is zero.min(1rem, 0)
. - The underside worth can be both
1rem
or the keyboard’s top. - The width on the desktop dimension is the same as the
--size
variable, and on cellular, it is going to take the total width, thus whyenv(keyboard-inset-width, 0)
is used. - Lastly, the
border-radius
could be both50px
or0
.
Neat, proper? I’ve by no means anticipated to provide you with such a demo. Do you assume it may very well be helpful? I’m excited to see what you’ll construct.
Linkedin submit kind and navigation
An instance that I noticed good potential for making use of the digital keyboard API is how the submit kind & navigation are proven for a Linkedin submit.
Think about the next determine:
The submit kind and navigation are mounted to the underside. When the consumer prompts the enter area, it seems like this:
Discover how the vertical actual property is just too small. What do to do? By mixing comparability features and the digital keyboard API, we will conceal the navigation when the keyboard is proven.
Right here is the CSS that does that.
.post-form,
.nav {
place: mounted;
left: 0;
proper: 0;
}
.post-form {
backside: max(48px, env(keyboard-inset-height, 0px));
}
.nav {
backside: max(0px, env(keyboard-inset-height, 0) - 100px);
}
Don’t fear, I’ll clarify it little by little.
Put up kind
Within the default state, the shape is offset by 48px
from the underside. On this state, the second a part of the max()
operate is inactive.
When the keyboard is energetic, the second a part of the max()
will work and the backside
worth will develop into the peak of the keyboard.
Navigation
The navigation is positioned at backside: 0
. The primary a part of the max()
operate is what’s energetic now.
When the keyboard is energetic, we’ll transfer the nav underneath the keyboard. The 100px
here’s a random quantity, the purpose is so as to add one thing that’s bigger than the navigation’s top.
Here’s a video of the way it works:
Demo on Codepen. You may also view all demos within the Codepen collections.
Outro
That’s it for this text. I realized lots in regards to the digital keyboard API and might’t wait to use it in my subsequent mission. The very last thing I anticipated is to put in writing 1600 phrases on such a subject. If which means something, it means to by no means belief your internal emotions about one thing you don’t know. Simply begin and the great issues will observe.
Do you’ve gotten any ideas or questions? Please be happy to ping me on Twitter (sorry, X) @shadeed9 or Mastodon or Threads.
Sources
The next sources helped me lots in my preliminary analysis in regards to the subject.
Thanks for studying.