Sometimes, it's because the layout code has some slight issues, where something is not allowed to shrink properly. Maybe it's a min-width
value on a grid item, for example. I can understand why you would want a minimum width for things in a grid, especially images, because you don't want things to shrink to a ridiculously tiny size.
Instead of using min-width
, let the browser do the calculation by using the minmax()
function. Then the browser will figure out how many columns you need. And you can still tweak until you happy. But okay, maybe there's an awkward width where no matter how much you tweak, at some point it looks weird. Are you stuck? Nooooo…
Consider adding breakpoints as required
Nobody said cannot use breakpoints
.grid {
grid-template-columns: repeat(2, 1fr);
}
@media screen and (min-width: 30em) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
Can add breakpoint! I mean, as good as it feels to be able to do things in a single line of code, nobody ever said cannot write more. It's not like there is a hard cap on how much code you can write, even though I would love to apply that to some people on some projects. With breakpoints, you can be even more specific on how you want the layout to be at every viewport you can control.
If word too long, then how?
Sometimes you have a really long word in the item that the browser won’t break. Watch Line breaking and related properties from CSS Text for in-depth explanation on line-breaking.
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Not a Hippopotamus, sometimes it's a URL like www.incomprehensibilities.com
Sometimes, it's not a layout issue per se. Maybe your items got some really really long string that the browser doesn't break up by default. Browsers are generally quite smart, and know how to speak many languages, you know why? Because dictionary. Anyway, line-breaking and word-breaking is a very non-trivial issue, beyond the scope of this talk, but I will link a nice video here, even though I doubt any of you will watch.
If the string doesn't really need to stay together, the easy way out is to word-break: break-all
. Problem solved. It's an inheritable property, so you can put it on the container or the item, up to you.
Is hyphenation a thing?
For visible hyphens use U+2010
or ‐
, while for invisible hyphens, use U+00AD
or ­
.
konservatorio konservatorio
põllumajandusministeerium
vervoerdersaansprakelijkheidsverzekering
vaðlaheiðarvegavinnuverkfærageymsluskúr
precipitevolissimevolmente
nebeprisikiškiakopūstlapiaujančiuosiuose
dziewięćdziesięciokilkuletniemu
anticonstitucionalmente
cyfrwngddarostynedigaeth
Browsers can do hyphenation, but it's a bit iffy still. Hyphenation is set to manual by default. When it is manual, it means you have to ownself hyphenate things. Like if you want hyphens that are always visible, then you use U+2010
or ‐
, while for invisible hyphens, use U+00AD
or ­
.
But this only makes sense if you have complete control over the content and markup. If you're not the one writing the content, can you even coordinate all your content writers to use ­
in their writing? What if you're using markdown? Then your content ends up a weird hybrid of HTML and markdown.
Browsers can do automatic hyphenation, but you must have the lang
attribute set correctly. Incorrect hyphenation makes the text really difficult to read. Browsers use dictionaries to figure out when hyphenations need to kick in, so tell your browser what language your content is in.
Even though browser support is reasonable, you try viewing this in Chrome, the hyphenation a bit off. It is what it is.
If nested scrolling…
Nested scrolling: when both the page and a component has overflow
https://codepen.io/wgao19/pen/BaVBvEY
Basic example
Component scroll blocks page scroll
Nested scrolling happens when both page and a component have scrolling. There will be stacked scrollbars. When users scroll inside the component, the page will stay at the same scroll position. When the component scroll position is at its bottom, try scrolling the component in the same direction — usually, it will resume scrolling the page, which is intended, as the internal overflow has finished scrolling.
But a tricky situation can happen when it sometimes doesn’t scroll the outer page. When this happens, the page is “stuck” at that scroll position as it constantly triggers the scrolling of the inner component only. Us developers “power users” may realize that we’re stuck in the inner component and therefore we can carefully put our fingers in the margin area and manually trigger the page scrolling again. But users may not be able to learn to do that and hence get themselves trapped.
…then how?
First, ask yourself:
Is it really necessary?
If it is —
give the page enough margin so it is easier for users to scroll the page
when intended
differentiate inner component and page more clearly, display the scrollbar,
etc.
Before trying to tackle this problem perhaps we can first ask ourselves whether the situation is really
necessary. Webpages intrinsically grow taller as the content grows, and phone screens are just a palm size,
what’s behind the necessity of having some nested region encapsulating long content instead of letting it
grow the page naturally?
And if the nested scrolling is deemed necessary, we need to help our users not get trapped in the stacked
scrollbar situation. Differentiate the regions more clearly, and make sure the page has enough margin so
users can scroll the page easily.
If stacked scrolling due to iFrame…
Trapped! Argh… 😩
No more stacked scrollbars from iFrame 😍
Sometimes the stacked scrolling may be introduced by iFrame. For example in the past two
years all climbing gyms in town required booking. And usually they embed the booking system on their website
using iFrame. After the iFrame loads page, which is usually a long table displaying timeslots, it introduces
a scrollbar in the iFrame and that often trapped me there.
But to my happy surprise this one of my favorite gyms in town has fixed it -- it now sets the height of the
iframe programmatically after the inner content loads. So how can you do that?
…you may try:
Statically setting the iFrame height to be a known height that is enough for its inner
content
Dynamically setting iFrame height
One naïve solution is the set the iFrame to be a sufficient height for its inner content. This works best
if the inner content has fixed height. Otherwise we may leave the parent page with empty space when the
inner content isn’t really that tall, and there’s no guarantee that the inner content won’t past our
predetermined height.
A more programmatic solution is to set the height of the iFrame when the inner content of the embedded page
finishes loading. This is not difficult if the inner page is of the same domain, in which case parent page
has direct access to the embedded page’s scroll height via contentWindow.body.scrollHeight
.
Otherwise, the two pages need to communicate using window.postMessage
which means the inner
page has to implement the relevant event for the parent page to tap into to get its height.
Maybe you wanted things to scroll horizontally…
e.g., a row of images overflowing the width of mobile screen with free horizontal scrolling
e.g., carousel where horizontal swiping triggers pagination
Nested scrolling can be of different direction. For example you may have a row of images to
be displayed on a narrow screen by introducing horizontal scroll.
Can is can, but…
Let's not do something like this:
Let's not do something like this
Personally speaking, I find this UI pretty acceptable — only when you don’t let me scroll
both directions at the same time. See the first example, there’s a carousel, users are expected to swipe (or
click) to paginate the carousel. But as they swipe, the page can move vertically as well. That doesn’t feel
very stable.
The touch-action
property
https://huijing.github.io/touch-action/
There is actually a CSS property called touch-action
that lets us block the
scrolling in the unintended direction when the component is intended to scroll only in one direction.
Panning done right
Credit: https://www.benjaminzander.org/
Here’s a webpage with carousels that implement proper panning CSS. When you swipe left and
right in the carousel sections, the page stays there and it feels more stable.
Scaling down a big, complex app to smaller screen
Just now Hui Jing mentioned how min-width
may become problematic layout. Now I'll share a case
where, despite potentially undesirable, perhaps is uneasy to change. And what workaround there may be to get
you some minimally usable web app that does not introduce unnecessary horizontal scrolling.
Imagine your app is originally built for big, desktop screens, perhaps a complex dashboard, or a highly developed e-commerce app. And for whatever legacy reason there is, the app already assumes a min-width that is causing overflow on tablets. And now the app is mature with many intricate features, built and supported by a handful of teams. And one day, your PM comes to you and say, “I think it’s time that we ship for tablets, because from our tracking data many users are using iPads.”
So they give you an iPad and the first thing you do? You open the app and boom, horizontal overflow.
Your goal is to make it minimally usable on tablets, and horizontal overflow is deemed not acceptable. So how? Do you go take down that min-width and then try to fix every component that breaks under smaller viewport? However you may want to fix them yourself, it may not be feasible because you may not even be able to know all the logical conditions of the whole app for each component to show.
The viewport
meta tag
<meta name="viewport" content="width=device-width, initial-scale=1" />
So I want to introduce you to one use case of the viewport meta tag which is often poorly understood.
Do you know that there are two viewports on mobile browsers?
The visual
viewport is the part of the page that’s currently shown on-screen. And the size follows the actual
screen size.
However, the CSS layout, especially
percentual widths, are calculated relative to the layout viewport , which can be
considerably wider than the visual viewport.
https://www.quirksmode.org/mobile/viewports2.html
This is very old technology. Ever since the very early days, the mobile browsers come with two viewports. A visual viewport which is roughly how big the mobile screen is (taking away the header and the footer, etc.). The user may scroll to change the part of the page he sees, or zoom to change the scale of the visual viewport.
And then there is layout viewport, which the mobile browser gives your webpage for layout purpose, so your CSS media queries will receive the dimensions of the layout viewport, not the visual viewport. Note that the dimensions of the layout viewport can be much bigger than the visual viewport, that’s how mobile browsers in the old days shrunk down very big desktop websites down to those tiny screens.
viewport
meta tag in action
Demo time!
<meta name="viewport" content="width=1600" />
First I want to show you how this app looks like on my iPad before doing anything. The app has min width 1500px, so it introduces a horizontal overflow because the viewport width is…
Now here's what happens when I add this viewport meta tag to the html head. It says to specify layout viewport to be fixed to 1600px. Now, you can see how the viewport width stays at 1600px. Even if I change orientation. And by giving my app this layout viewport bigger than its min-width, it will always scale nicely and there will be no horizontal overflow.
This is not a trick. In fact, if you don’t set any viewport meta tag at all, and if the browser sees your content is much wider than the mobile screen, on iPad / iOS it will render a default layout viewport sized at 980px. I think we as users are are so used to this behavior we don’t even think eh how come my site is much bigger but it renders just nice on my iPad mini?
But then hor…
By setting the layout viewport tag for this purpose, it “invalidates” responsive design
There’s a discrepancy between “layout size” and “actual size” of a component
Fonts can end up too small
By setting the layout viewport tag for this purpose, it “invalidates” responsive design on the site because
on mobile screens it now always renders a fixed viewport size.
There’s a discrepancy between “layout size” and “actual size” of a component, so it becomes slightly more
difficult for you to manually size your component too, you need to always pretend your screen is of certain
size (depending how you see it and how your app functions, this could be a bonus lol).
Fonts can be too shrunken.
Not just a technical problem though
What if your website owner is not a technical person and has no developers around them?
I know this is Geekcamp, so we must talk technical stuff, for the most part. But a lot of times, the technical solutions are easier to come up with than the people/business side problems. Sometimes we hang out with each other too much, and take for granted that a lot of people actually have no idea what we do for a living. Like my mom.
If I made my mom sit through whatever we just talked about for the past half an hour, she would probably either, ask me to explain everything again five more times, and complain I'm not explaining clearly enough, or instead ask me to just fix her printer problem. The point is, not everyone that runs a website is a developer themselves.
This problem, I have no meaningful answer. It's just something for everyone to ponder about I guess.