diff --git a/dotcom-rendering/src/components/GalleryCaption.tsx b/dotcom-rendering/src/components/GalleryCaption.tsx index 26a71ba6205..9b5cf754a00 100644 --- a/dotcom-rendering/src/components/GalleryCaption.tsx +++ b/dotcom-rendering/src/components/GalleryCaption.tsx @@ -31,34 +31,10 @@ const styles = css` ${between.desktop.and.leftCol} { ${grid.column.right} - - position: relative; /* allows the ::before to be positioned relative to this */ - - &::before { - content: ''; - position: absolute; - left: -10px; /* 10px to the left of this element */ - top: 0; - bottom: 0; - width: 1px; - background-color: ${palette('--article-border')}; - } } ${from.leftCol} { ${grid.column.left} - - position: relative; /* allows the ::before to be positioned relative to this */ - - &::after { - content: ''; - position: absolute; - right: -11px; - top: -12px; - bottom: 0; - width: 1px; - background-color: ${palette('--article-border')}; - } } `; diff --git a/dotcom-rendering/src/components/GalleryImage.tsx b/dotcom-rendering/src/components/GalleryImage.tsx index 5ce317dcd10..8907b414ac2 100644 --- a/dotcom-rendering/src/components/GalleryImage.tsx +++ b/dotcom-rendering/src/components/GalleryImage.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/react'; import { isUndefined } from '@guardian/libs'; -import { from, space, until } from '@guardian/source/foundations'; +import { between, from, space, until } from '@guardian/source/foundations'; import { grid } from '../grid'; import { type ArticleFormat } from '../lib/articleFormat'; import { getImage } from '../lib/image'; @@ -22,8 +22,9 @@ type Props = { }; const styles = css` + overflow: hidden; ${grid.paddedContainer} - ${grid.verticalRules()} + ${grid.verticalRules({ plusChild: 1 })} grid-auto-flow: row dense; background-color: ${palette('--article-inner-background')}; @@ -34,9 +35,15 @@ const styles = css` ${from.desktop} { &:first-of-type { - padding-top: ${space[3]}px; + & > * { + padding-top: ${space[3]}px; + } } } + + ${between.desktop.and.leftCol} { + ${grid.verticalRules({ plusChild: 2 })} + } `; const galleryBodyImageStyles = css` diff --git a/dotcom-rendering/src/grid.ts b/dotcom-rendering/src/grid.ts index f60ae0ffc5d..caaaf8f8c70 100644 --- a/dotcom-rendering/src/grid.ts +++ b/dotcom-rendering/src/grid.ts @@ -88,36 +88,58 @@ const paddedContainer = ` // ----- Vertical Rules ----- // type VerticalRuleOptions = { - centre?: boolean; color?: string; + plusChild?: number; }; /** * Render Guardian grid vertical rules. * * Left and right rules are always present. - * A centre rule can optionally be enabled. + * A centre rule can optionally be enabled, anchored to the nth + * child of the grid container as specified by the `plusChild` option * * Usage: * css([grid.container, grid.verticalRules()]) - * css([grid.container, grid.verticalRules({ centre: true })]) + * css([grid.container, grid.verticalRules({ plusChild: 3 })]) */ -const optionalCentreRule = `/* CENTRE RULE */ - & > *:first-child::before { - grid-column: centre-column-start; - transform: translateX(-${columnGap}); - ${fromBreakpoint.leftCol} { - transform: translateX(calc(-${columnGap} / 2)); - } + +// The centre rule is self-contained on the nth child element rather than on +// the grid container, so that `top: 0` aligns to that element's top edge. +// `bottom` uses a large negative value to extend the rule down to the +// container's bottom; ensure `overflow: hidden` is set on the container +const optionalCentreRule = ( + nth: number, + color?: string, +): string => `/* CENTRE RULE */ + & > *:nth-child(${nth}) { + position: relative; + + &::before { + position: absolute; + top: 0; + bottom: -9999px; + width: 1px; + background-color: ${color ?? palette('--article-border')}; + content: ''; + grid-column: centre-column-start; + transform: translateX(-${columnGap}); + + ${fromBreakpoint.desktop} { + transform: translateX(calc(-${columnGap} / 2)); + } + } }`; -const verticalRules = (options: VerticalRuleOptions = {}): string => ` +const verticalRules = (options: VerticalRuleOptions = {}): string => { + const { plusChild, color } = options; + + return ` ${fromBreakpoint.tablet} { position: relative; &::before, - &::after - ${options.centre ? ', & > *:first-child::before' : ''} { + &::after { position: absolute; top: 0; bottom: 0; @@ -146,8 +168,9 @@ const verticalRules = (options: VerticalRuleOptions = {}): string => ` } } - ${options.centre ? optionalCentreRule : ''} -`; + ${plusChild !== undefined ? optionalCentreRule(plusChild, color) : ''} + }`; +}; // ----- API ----- //