Repository navigation
Lay out the organizers page, and cut the photos square - #199
Merged
Merged
Conversation
ber2
approved these changes
Oct 5, 2026
This was referenced Oct 5, 2026
DZPM
force-pushed
the
work/check-rendered
branch
from
October 7, 2026 09:24
193a879 to
2418c19
Compare
people_per_line went into a Bootstrap column class, col-md-{12/N}. Twelve
divides by 1, 2, 3, 4, 6 and 12, so any other value was rounded without a
word: five asked for col-md-2, which is six cards to a row. The width now
comes from a per_line_N class that takes a fraction of the row, so the
number asked for is the number shown.
The count steps up with the viewport. Five cards on a 768px screen leave
114px each, too narrow for a name, so a row holds three from 768px, four
from 992px, and the full count from 1200px.
The card is a flex column, so every card in a row ends at the same height
and the social links sit on the bottom edge whatever the length of the role
above them. They were positioned absolutely before, against an ancestor far
up the page, because this box was never positioned itself.
The icons are a centred flex row. As inline-block they were separated by
the whitespace between the tags, about 4px each, which was enough to push
the fourth icon of a narrow card onto a second line. Flex drops those text
nodes, so the spacing is the one set here and nothing else.
The border takes the brand blue on hover and on focus-within, so the card
the pointer or the keyboard is on is obvious.
The organizers page asks for five to a row in its first three sections, and
the section titles now name the year each board belongs to.
Font Awesome 5.8.2 predates the rename and carries no X icon. Upgrading the vendored set to a 6.x release for one glyph would change every other icon on the site, so the mark is drawn from the Font Awesome 6 Free path as a CSS mask instead. It takes its colour from currentColor, so it follows the same colour and hover rules as the glyphs beside it, and it costs no extra request. The person cards, the bio dialogs and the footer all use it. The labels now say X rather than Twitter. Every social link also gains a title, so a pointer gets the same name a screen reader already had. The twitter key keeps its name in the person front matter, and the links still point at twitter.com, which redirects. Renaming the key would touch every person file that has one, for no gain today.
The site serves every person photo as a square. The square was cut at build time, which costs twice: the crop is picked by a rule that does not know where the face is, and the repository carries sources far larger than anything the site ever serves. bin/square-photos cuts it once, here, so the crop is reviewable in a pull request like any other change and the build only resizes. It finds the face with OpenCV, crops the largest square it can centre on that face, and resizes to at most 800px, which is what the 2x variant of a 400px grid slot needs. It never enlarges. A 200px photo blown up to 800 is the same picture in four times the bytes, so the 27 photos under 400px stay small and the check reports them. Picking the right face took three attempts, and each wrong one was found by looking at the output rather than by reasoning about it, which is the argument for cutting the crop here instead of in the build. The cascade returns several boxes per portrait. Taking the largest put the crop on a subject's torso. Taking the most confident put it on a 59px patch of background while the real face, ten times wider, scored lower. Dropping every box wider than 60% of the short side fixed the first and broke a close selfie whose face really is 64% of it. Width alone cannot tell a selfie from a torso; the score can, 7.27 against 1.72. So a wide box survives when it is confident, and the largest survivor wins. One photo carries EXIF Orientation 5. A browser honours that tag and shows the picture upright, so the site looked right while every tool reading the pixels saw it on its side. The rotation is now in the pixels and the tag is gone. 66 of the 132 photos changed. The sources go from 38.7 MB to 12.2 MB and the largest file from 5.0 MB to 755 KB. All 132 are now square. check-content rejects a photo that is not square, one over 1200px, and one over 1000 KB. That last one is for the pull request nobody reads closely: a photo straight off a phone is several megabytes and tens of megapixels, and it costs the repository that much for ever.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #196. Its base is
work/check-rendered, so the diff shows only this pull request's own changes. GitHub retargets it as the ones below merge.Everything about how a person appears on the site: the layout of the grid, the icon beside their name, and the photo itself.
Five to a row, because five is what the page asks for
people_per_linewent intocol-md-{{ div 12 N }}. Twelve divides by 1, 2, 3, 4, 6 and 12, so any other value was rounded without a word:people_per_line: 5producedcol-md-2, which is six cards to a row. The width now comes from aper_line_Nclass that takes a fraction of the row, so the number asked for is the number shown.The count steps down on a narrow screen, because five cards at 768px leave 114px each. A row holds three from 768px, four from 992px, and the full count from 1200px.
One shape per card
The card is a flex column, so every card in a row ends at the same height and the social links sit on the bottom edge whatever the length of the role above them. They were positioned absolutely before, against an ancestor far up the page, because
.person_itemwas never positioned itself. They were in the right place by luck.The icons are a centred flex row. As
inline-blockthey were separated by the whitespace between the tags, about 4px each, which was enough to push the fourth icon of a narrow card onto a second line. Measured in headless Chromium at seven viewport widths from 360 to 1920: no card wraps its icons at any of them.The border takes the brand blue on hover and on
focus-within.The X mark
Font Awesome 5.8.2 predates the rename and carries no X icon. Upgrading the vendored set to a 6.x release for one glyph would change every other icon on the site, so the mark is drawn from the Font Awesome 6 Free path as a CSS mask instead. It takes its colour from
currentColor, so it follows the same colour and hover rules as the glyphs beside it, and it costs no extra request.Person cards, bio dialogs and the footer all use it, and every social link gains a
title, so a pointer gets the name a screen reader already had.The photos are cut square here, not on every build
The site serves every person photo as a square. The square was cut at build time, which costs twice: the crop is picked by a rule that does not know where the face is, and the repository carries sources far larger than anything the site ever serves.
bin/square-photoscuts it once, so the crop is reviewable in a pull request like any other change and the build only resizes. It finds the face with OpenCV, crops the largest square it can centre on that face, and resizes to at most 800px.It never enlarges, so the 27 photos under 400px stay small and the check reports them. It does not zoom in either: a full-length shot on a beach stays a full-length shot on a beach, and the fix for those is a different photo.
66 of the 132 photos changed.
Picking the right face took three attempts, and each wrong one was found by looking at the output. The cascade returns several boxes per portrait. Taking the largest put the crop on a subject's torso. Taking the most confident put it on a 59px patch of background while the real face, ten times wider, scored lower. Dropping every box wider than 60% of the short side fixed the first and broke a close selfie whose face really is 64% of it. Width alone cannot tell a selfie from a torso; the score can, 7.27 against 1.72. So a wide box survives when it is confident, and the largest survivor wins.
One photo carries EXIF
Orientation5. A browser honours that tag and shows the picture upright, so the site looked right while every tool reading the pixels saw it on its side. The rotation is now in the pixels and the tag is gone.bin/check-contentrejects a photo that is not square, one over 1200px, and one over 1000 KB. That last limit is for the pull request nobody reads closely: a photo straight off a phone is several megabytes and tens of megapixels, and it costs the repository that much for ever. Verified by planting a 900x600 photo and a 1500x1500 one.How it was checked
The four checks pass. The layout was measured in headless Chromium rather than eyeballed, and every crop was reviewed one by one against the original before being applied.