explorer / frontend /src /styles /responsive.css
noobpwnftw's picture
Deploy ChessTB Explorer on Hugging Face Spaces
e16348e
Raw History Blame
6.45 kB
/* ── Responsive layout ─────────────────────────────────────────────────
At 1180px and below the columns wrap: the board column takes a
full-width row and the results and PGN columns wrap beneath it. Sizes
are authored in rem. */
@media (max-width: 1180px) {
html, body { height: auto; overflow-y: auto; }
:root { --pgn-col-w: 18.75rem; }
.content {
grid-template-columns: minmax(0, 1fr) var(--pgn-col-w);
height: auto;
overflow: visible;
padding: var(--space-4);
}
.left-col {
grid-column: 1 / -1;
height: auto;
}
/* Horizontal auto margins centre a fixed-width flex item on the
cross axis of a column-direction container. */
.board-group { margin: 0 auto; }
.right-col, .pgn-col {
height: min(60vh, 520px);
}
}
/* ── Phone: swipeable screens ───────────────────────────────────────────
Below 768px the layout is three horizontally swipeable screens in
column order: board, results, PGN. Each screen fills the space between
the header and the bottom screen navigation; a horizontal swipe moves
to the next one, while a vertical swipe scrolls that screen's own
content. The board is sized to the visible height so the whole board
screen fits; below its 14rem floor the screen scrolls from the top. */
@media (max-width: 767px) {
:root {
--screen-nav-h: calc(3rem + env(safe-area-inset-bottom, 0px));
--viewport-h: 100vh;
/* Fixed heights above and around the board: three control rows,
column padding 1rem, gaps 1.875rem, error line 0.875rem plus
0.5rem slack, tray padding 1.25rem and tray borders 4px. The
remainder holds the board and its two trays: 1.25 x board.
Update when the height above the board changes. */
--board-fit-h: calc((var(--viewport-h) - var(--header-h) - var(--screen-nav-h) - 5.5rem - 3 * var(--control-h) - 4px) / 1.25);
--board-size: max(14rem, min(var(--board-size-cap), var(--board-fit-h)));
}
@supports (height: 100dvh) {
:root { --viewport-h: 100dvh; }
}
html, body { overflow-x: hidden; }
.content {
grid-template-columns: repeat(3, 100vw);
overflow-x: auto;
overflow-y: hidden;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
min-height: 0;
height: calc(100vh - var(--header-h) - var(--screen-nav-h));
height: calc(100dvh - var(--header-h) - var(--screen-nav-h));
width: 100vw;
max-width: none;
padding: 0;
gap: 0;
}
.left-col, .right-col, .pgn-col {
grid-column: auto;
max-width: 100vw;
min-height: 0;
height: calc(100vh - var(--header-h) - var(--screen-nav-h));
height: calc(100dvh - var(--header-h) - var(--screen-nav-h));
scroll-snap-align: start;
/* Containing block for absolutely positioned descendants (e.g. .sr-only). */
position: relative;
}
.left-col {
overflow-y: auto;
padding: var(--space-2) var(--space-4);
}
.board-group { margin: 0 auto; }
.right-col, .pgn-col { padding: var(--space-4); overflow: hidden; }
/* Logo and nav span two rows; the subtitle sits below the title. */
.site-header {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
grid-template-rows: auto auto;
align-content: center;
column-gap: 0.625rem;
row-gap: 0;
}
.site-header__logo, .site-header__nav { grid-row: 1 / span 2; }
.site-header__brand { display: contents; }
.site-header__sep { display: none; }
.site-header__title, .site-header__sub {
grid-column: 2;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.2;
}
.site-header__title { grid-row: 1; align-self: end; }
.site-header__sub { grid-row: 2; align-self: start; font-size: 0.6875rem; }
.screen-nav { display: grid; }
.toast-container { bottom: calc(var(--screen-nav-h) + var(--space-3)); }
/* The moves list owns vertical panning so a drag on it is not claimed
by .content's horizontal scroll-snap. */
.moves-body-scroll {
touch-action: pan-y;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: contain;
}
/* The table spans the full screen width, so it is not widened for the scrollbar. */
.moves-body-scroll.has-vscroll .moves-table--body { width: 100%; }
.move-line { --pgn-rank-width: var(--pgn-rank-w-compact); }
}
@media (max-width: 480px) {
:root { --board-size-cap: min(360px, 88vw); }
.left-col, .right-col, .pgn-col {
padding-left: max(var(--space-4), env(safe-area-inset-left));
padding-right: max(var(--space-4), env(safe-area-inset-right));
}
.site-header {
padding-left: max(var(--space-5), env(safe-area-inset-left));
padding-right: max(var(--space-5), env(safe-area-inset-right));
}
/* Title, count and CSV button do not fit one row at this width. */
.panel-header { flex-wrap: wrap; row-gap: 6px; }
/* .btn--grow deliberately doesn't shrink (readable label + icon at
any width) - six buttons can't all fit one row this narrow, so
the toolbar wraps instead of overflowing. */
.fen-actions { flex-wrap: wrap; row-gap: 6px; }
}
/* ── Touch input sizing ─────────────────────────────────────────────────
(hover: none) and (pointer: coarse) targets touchscreens regardless of
viewport width. Control heights come from --control-h in tokens.css.
Inputs use a >=16px font size because iOS Safari zooms the page when a
focused input's font size is under 16px. */
@media (hover: none) and (pointer: coarse) {
.fen-input { font-size: var(--text-lg); }
.pgn-dialog__textarea { font-size: var(--text-lg); }
/* #board handles its own drag gestures; letting the browser also
interpret them as page-scroll/pinch-zoom fights the drag. */
.spare-piece, .promotion-piece-btn { touch-action: none; }
}