A few years ago we switched to [Flexbox 
Layout](https://developer.mozilla.org/en-US/docs/Glossary/Flexbox) to implement 
the sticky header in the API docs generated by `javadoc`. This solved the 
problem of anchor link targets [not being positioned 
correctly](https://bugs.openjdk.org/browse/JDK-8223378), but it also introduced 
a few new ones:

 - It required a workaround to get browser history to work (JDK-8249133, 
JDK-8250779, 8286832)
 - It changed certain aspects of scrolling behavior in the browser (JDK-8301080)
 - It changed the way some CSS properties are interpreted (JDK-8315800)

The reason for most of these problems is that the layout paradigm used by 
Flexbox is very different from traditional layout of HTML pages. The 
`scroll-margin-*` CSS properties introduced by the [CSS Scroll Snap 
Module](https://www.w3.org/TR/css-scroll-snap-1/) provide a simpler and less 
intrusive way to implement link target offsets in combination with sticky 
elements implemented using [`position: 
sticky`](https://developer.mozilla.org/en-US/docs/Web/CSS/position). However, 
although it is implemented [in all supported 
browsers](https://caniuse.com/?search=scroll-margin), it comes with its own 
challanges and quirks, which are explained below.

The first problem to overcome was that `position: sticky` is more fragile on 
mobile browsers than Flexbox. If some part of the page content overflows the 
allotted horizontal space, the whole page can be zoomed out to view the whole 
content. This causes the header to become unsticky and the link target offsets 
to become erroneous. It was therefore necessary to make sure page content never 
overflows its allotted horizontal space, either by adding line break 
opportunities, or by making all or part of the page horizontally scrollable 
when its content overflows. Line break opportunities are difficult to add 
especially in  preformatted code, so I opted for making the parts of the page 
most likely containing long lines of code scrollable. 

The next problem was that enabling horizontal scrolling on an element or one of 
its containing elements breaks the `scroll-margin-top` property in Chrome due 
to a browser quirk (both desktop and mobile versions). This means that the 
scrolling must occur in a child element rather than the sections or other 
elements serving as link targets. 

When enabling horizontal scrolling on the contents of sections containing 
user-provided content, another problem is that it disables [Margin 
Collapse](https://www.joshwcomeau.com/css/rules-of-margin-collapse/) which 
regulates margins between adjacent and contained boxes. Since these sections 
can contain a mix of HTML containers, it is almost impossible to preserve the 
margins between elements while making them scrollable. 

The solution to these problems was to add a new `<div 
class="horizontal-scroll">` to the sections containing user-provided content. 
Adding a single scrollable element per section allowed the margins to be 
controlled in a relatively safe way, although some CSS is introduced to limit 
the margin of certain trailing block elements in certain sections. 

The `scroll-margin-top` property is set to the normal height of the sticky 
header in `stylesheet.css`, with a line added to `search.js` to set the 
property dynamically to the actual header height to accommodate for the 
pre-release notification banner. In a previous version of this branch, the 
pre-release banner was excluded from the sticky header, but it was made sticky 
again in the final version to make the output more comparable. 

The generated documentation should render the same on supported browsers pixel 
by pixel. Before/after snapshots of the JDK docs are available here:

Before: https://cr.openjdk.org/~hannesw/8308659/api.00/
After: https://cr.openjdk.org/~hannesw/8308659/api.01/

-------------

Commit messages:
 - Rename local variable
 - Make enum constant detail scrollable
 - Avoid nested rules
 - Fix summary page table headers
 - More CSS changes
 - Further cleanup
 - Refine style adaptations
 - Update copyright header dates
 - JDK-8308659: Use CSS scroll-margin instead of flexbox layout in API 
documentation

Changes: https://git.openjdk.org/jdk/pull/15969/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=15969&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8308659
  Stats: 296 lines in 38 files changed: 108 ins; 75 del; 113 mod
  Patch: https://git.openjdk.org/jdk/pull/15969.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/15969/head:pull/15969

PR: https://git.openjdk.org/jdk/pull/15969

Reply via email to