From 004c13a65999d5e8a5a7bb23aa17ba20ce581bc9 Mon Sep 17 00:00:00 2001 From: Jake Lee Kennedy Date: Thu, 31 Oct 2024 16:07:04 +0000 Subject: [PATCH] reorganise ad styles --- .../src/components/AdSlot.web.tsx | 218 +++------------- .../src/components/ArticleContainer.tsx | 141 +---------- .../src/components/Discussion/Comments.tsx | 3 +- .../src/components/DiscussionLayout.tsx | 3 +- .../src/components/HeaderAdSlot.tsx | 16 +- .../src/layouts/FullPageInteractiveLayout.tsx | 7 +- dotcom-rendering/src/lib/ArticleRenderer.tsx | 10 +- dotcom-rendering/src/lib/adStyles.ts | 239 ++++++++++++++++++ dotcom-rendering/src/lib/rootStyles.ts | 6 +- 9 files changed, 291 insertions(+), 352 deletions(-) create mode 100644 dotcom-rendering/src/lib/adStyles.ts diff --git a/dotcom-rendering/src/components/AdSlot.web.tsx b/dotcom-rendering/src/components/AdSlot.web.tsx index 151407177f3..d63300b114a 100644 --- a/dotcom-rendering/src/components/AdSlot.web.tsx +++ b/dotcom-rendering/src/components/AdSlot.web.tsx @@ -1,16 +1,15 @@ import { css } from '@emotion/react'; import type { SlotName } from '@guardian/commercial'; -import { adSizes, constants } from '@guardian/commercial'; +import { adSizes } from '@guardian/commercial'; import { between, breakpoints, from, palette, - space, - textSans12, until, } from '@guardian/source/foundations'; import { Hide } from '@guardian/source/react-components'; +import { labelBoxStyles, labelHeight, labelStyles } from '../lib/adStyles'; import { ArticleDisplay } from '../lib/articleFormat'; import { getZIndex } from '../lib/getZIndex'; import { LABS_HEADER_HEIGHT } from '../lib/labs-constants'; @@ -68,84 +67,12 @@ type RemainingProps = { */ type Props = DefaultProps & (RightProps | InlineProps | RemainingProps); -const labelHeight = constants.AD_LABEL_HEIGHT; const halfPageAdHeight = adSizes.halfPage.height; -const individualLabelCSS = css` - ${textSans12}; - height: ${labelHeight}px; - max-height: ${labelHeight}px; - background-color: ${schemedPalette('--ad-background')}; - padding-top: 3px; - border-top: 1px solid ${schemedPalette('--ad-border')}; - color: ${schemedPalette('--ad-labels-text')}; - text-align: center; - box-sizing: border-box; -`; - const outOfPageStyles = css` height: 0; `; -export const labelStyles = css` - .ad-slot__scroll { - ${individualLabelCSS} - position: relative; - &.visible { - visibility: initial; - } - &.hidden { - visibility: hidden; - } - } - .ad-slot__close-button { - display: none; - } - - .ad-slot__scroll { - position: fixed; - bottom: 0; - width: 100%; - ${individualLabelCSS} - } - - .ad-slot:not[data-label-show='true']::before { - content: ''; - display: block; - height: ${labelHeight}px; - visibility: hidden; - } - - .ad-slot[data-label-show='true']:not(.ad-slot--interscroller)::before { - content: attr(ad-label-text); - display: block; - position: relative; - ${individualLabelCSS} - } - - .ad-slot__adtest-cookie-clear-link { - ${textSans12}; - text-align: left; - position: absolute; - left: 268px; - top: 1px; - z-index: 10; - padding: 0; - border: 0; - } - - .ad-slot--interscroller[data-label-show='true']::before { - content: 'Advertisement'; - position: absolute; - top: 0; - left: 0; - right: 0; - border: 0; - display: block; - ${individualLabelCSS} - } -`; - const darkLabelStyles = css` .ad-slot[data-label-show='true']:not(.ad-slot--interscroller)::before { background-color: transparent; @@ -154,25 +81,6 @@ const darkLabelStyles = css` } `; -const adContainerCollapseStyles = css` - & .ad-slot.ad-slot--collapse { - display: none; - } -`; - -const adContainerCentreSlotStyles = css` - &.ad-slot-container--centre-slot { - width: fit-content; - margin: 0 auto; - } -`; - -const adSlotCollapseStyles = css` - &.ad-slot.ad-slot--collapse { - display: none; - } -`; - /** * For CSS in Frontend, see mark: 9473ae05-a901-4a8d-a51d-1b9c894d6e1f */ @@ -246,15 +154,6 @@ const merchandisingAdStyles = css` } `; -const inlineAdStyles = css` - position: relative; - background-color: ${schemedPalette('--ad-background-article-inner')}; - - ${until.tablet} { - display: none; - } -`; - const rightAdStyles = css` background-color: ${schemedPalette('--ad-background-article-inner')}; max-width: 300px; @@ -401,28 +300,6 @@ const liveBlogTopContainerStyles = css` display: flex; justify-content: center; `; -/** - * For implementation in Frontend, see mark: dca5c7dd-dda4-4922-9317-a55a3789fe4c - * These styles come mostly from RichLink in DCR. - */ -export const carrotAdStyles = css` - .ad-slot--carrot { - float: left; - clear: both; - width: 140px; - margin-right: 20px; - margin-bottom: ${space[1]}px; - ${from.leftCol} { - position: relative; - margin-left: -160px; - width: 140px; - } - ${from.wide} { - margin-left: -240px; - width: 220px; - } - } -`; const mobileStickyAdStyles = css` position: fixed; @@ -476,7 +353,7 @@ const mobileStickyAdStyles = css` content: 'Advertisement'; display: block; position: relative; - ${individualLabelCSS} + ${labelBoxStyles} } `; @@ -491,12 +368,6 @@ const mobileStickyAdStylesFullWidth = css` } `; -export const adContainerStyles = [ - adContainerCollapseStyles, - labelStyles, - adContainerCentreSlotStyles, -]; - export const AdSlot = ({ position, display, @@ -511,10 +382,7 @@ export const AdSlot = ({ switch (display) { case ArticleDisplay.Immersive: { return ( -
+
+
); } - case 'inline': { - const advertId = `inline${index + 1}`; - return ( -
- - ); - } + // case 'inline': { + // const advertId = `inline${index + 1}`; + // return ( + //
+ // + // ); + // } case 'liveblog-inline': { const advertId = `inline${index + 1}`; return ( -
+
+
+
+
+
{ return ( -
+
{children}
); diff --git a/dotcom-rendering/src/components/Discussion/Comments.tsx b/dotcom-rendering/src/components/Discussion/Comments.tsx index caf25fe2fe1..e9a7b375f0e 100644 --- a/dotcom-rendering/src/components/Discussion/Comments.tsx +++ b/dotcom-rendering/src/components/Discussion/Comments.tsx @@ -13,7 +13,6 @@ import type { import type { preview, reportAbuse } from '../../lib/discussionApi'; import { getPicks, initialiseApi } from '../../lib/discussionApi'; import { palette as schemedPalette } from '../../palette'; -import { labelStyles } from '../AdSlot.web'; import { useConfig } from '../ConfigContext'; import { useDispatch } from '../DispatchContext'; import { CommentContainer } from './CommentContainer'; @@ -440,7 +439,7 @@ export const Comments = ({ ) : (
    {comments.map((comment) => ( diff --git a/dotcom-rendering/src/components/DiscussionLayout.tsx b/dotcom-rendering/src/components/DiscussionLayout.tsx index 6aae80bee83..cdf810fb370 100644 --- a/dotcom-rendering/src/components/DiscussionLayout.tsx +++ b/dotcom-rendering/src/components/DiscussionLayout.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/react'; import { from } from '@guardian/source/foundations'; import { ArticleDisplay, type ArticleFormat } from '../lib/articleFormat'; import type { RenderingTarget } from '../types/renderingTarget'; -import { AdSlot, labelStyles } from './AdSlot.web'; +import { AdSlot } from './AdSlot.web'; import { useConfig } from './ConfigContext'; import { DiscussionApps } from './DiscussionApps.importable'; import { DiscussionMeta } from './DiscussionMeta.importable'; @@ -123,7 +123,6 @@ export const DiscussionLayout = ({ gap: 100vh; height: 100%; `, - labelStyles, ]} >
    diff --git a/dotcom-rendering/src/layouts/FullPageInteractiveLayout.tsx b/dotcom-rendering/src/layouts/FullPageInteractiveLayout.tsx index 1b48ee19e57..575300b4c02 100644 --- a/dotcom-rendering/src/layouts/FullPageInteractiveLayout.tsx +++ b/dotcom-rendering/src/layouts/FullPageInteractiveLayout.tsx @@ -4,10 +4,7 @@ import { palette as sourcePalette, until, } from '@guardian/source/foundations'; -import { - adContainerStyles, - MobileStickyContainer, -} from '../components/AdSlot.web'; +import { MobileStickyContainer } from '../components/AdSlot.web'; import { Footer } from '../components/Footer'; import { HeaderAdSlot } from '../components/HeaderAdSlot'; import { Island } from '../components/Island'; @@ -108,8 +105,6 @@ const Renderer = ({ }); const adStyles = css` - ${adContainerStyles} - ${from.tablet} { .mobile-only .ad-slot { display: none; diff --git a/dotcom-rendering/src/lib/ArticleRenderer.tsx b/dotcom-rendering/src/lib/ArticleRenderer.tsx index 028cd0f0b5b..1560c8725ef 100644 --- a/dotcom-rendering/src/lib/ArticleRenderer.tsx +++ b/dotcom-rendering/src/lib/ArticleRenderer.tsx @@ -1,10 +1,10 @@ import { css } from '@emotion/react'; -import { adContainerStyles } from '../components/AdSlot.web'; import { useConfig } from '../components/ConfigContext'; import { interactiveLegacyClasses } from '../layouts/lib/interactiveLegacyStyling'; import type { ServerSideTests, Switches } from '../types/config'; import type { FEElement } from '../types/content'; import type { TagType } from '../types/tag'; +// import { adContainerStyles } from './adStyles'; import { ArticleDesign, type ArticleFormat } from './articleFormat'; import type { EditionId } from './edition'; import { RenderArticleElement } from './renderElement'; @@ -20,9 +20,9 @@ const commercialPosition = css` // // spacefinder is scoped to placing elements in spaces within the .article-body-commercial-selector // hence we scope the styles at the same level -const adStylesDynamic = css` - ${adContainerStyles} -`; +// const adStylesDynamic = css` +// ${adContainerStyles} +// `; type Props = { format: ArticleFormat; @@ -111,7 +111,7 @@ export const ArticleRenderer = ({ ? interactiveLegacyClasses.contentMainColumn : '', ].join(' ')} - css={[adStylesDynamic, commercialPosition]} + css={[commercialPosition]} > {renderingTarget === 'Apps' ? renderedElements diff --git a/dotcom-rendering/src/lib/adStyles.ts b/dotcom-rendering/src/lib/adStyles.ts new file mode 100644 index 00000000000..81e59da7126 --- /dev/null +++ b/dotcom-rendering/src/lib/adStyles.ts @@ -0,0 +1,239 @@ +import { css } from '@emotion/react'; +import { adSizes, constants } from '@guardian/commercial'; +import { from, space, textSans12, until } from '@guardian/source/foundations'; +import { palette } from '../palette'; + +const labelHeight = constants.AD_LABEL_HEIGHT; + +export const labelBoxStyles = css` + ${textSans12}; + height: ${labelHeight}px; + max-height: ${labelHeight}px; + background-color: ${palette('--ad-background')}; + padding-top: 3px; + border-top: 1px solid ${palette('--ad-border')}; + color: ${palette('--ad-labels-text')}; + text-align: center; + box-sizing: border-box; +`; + +const labelStyles = css` + .ad-slot[data-label-show='true']::before { + content: attr(ad-label-text); + display: block; + position: relative; + ${labelBoxStyles} + } + + .ad-slot[data-label-show='true'].ad-slot--interscroller::before { + display: none; + } + + .ad-slot__adtest-cookie-clear-link { + ${textSans12}; + text-align: left; + position: absolute; + left: 268px; + top: 1px; + z-index: 10; + padding: 0; + border: 0; + } +`; + +const adContainerCentreSlotStyles = css` + &.ad-slot-container--centre-slot { + width: fit-content; + margin: 0 auto; + } +`; + +// const adContainerStyles = [labelStyles, adContainerCentreSlotStyles]; + +const adSlotContainerStyles = css` + .ad-slot-container { + max-width: 100vw; + position: relative; + } +`; + +const inlineAdSlotContainerStyles = css` + .ad-slot-container { + margin: 12px auto; + text-align: center; + display: flex; + justify-content: center; + + ${from.tablet} { + background-color: ${palette('--ad-background')}; + } + + /* Prevent merger with any nearby float left elements e.g. rich-links */ + ${until.desktop} { + clear: left; + } + + .ad-slot--interscroller { + /* this fixes inter-scrollers stealing mouse events */ + overflow: hidden; + position: relative; + + /* position the iframe absolutely (relative to the slot) so that it is in the correct position to detect viewability */ + .ad-slot__content { + position: absolute; + height: 100%; + left: 0; + top: 0; + right: 0; + + /* must be behind as the actual ad is on top of the iframe */ + z-index: -1; + } + } + } + + /* + Some ads are in the right column, inline2+ for example. +*/ + .ad-slot-container--offset-right { + ${from.desktop} { + float: right; + max-width: 300px; + margin-right: -330px; + background-color: transparent; + } + + ${from.leftCol} { + margin-right: -310px; + } + + ${from.wide} { + margin-right: -400px; + } + } +`; + +const adSlotStyles = css` + .ad-slot { + /* this is centring the ad iframe as they are display: inline; elements by default */ + text-align: center; + + ${from.tablet} { + /* from tablet the ad slot will stretch to the full width of the container and the iframe will be centred by the text-align: center; on the container */ + flex: 1; + /* Ensures slots do not take on 100% of the container height, allowing them to be sticky in containers */ + align-self: flex-start; + } + + /* + Ensure that the ad slot is centred, + the element with this class name is inserted by GAM into the ad slot + */ + .ad-slot__content { + margin-left: auto; + margin-right: auto; + } + + @media print { + /* stylelint-disable-next-line declaration-no-important */ + display: none !important; + } + + &.ad-slot--collapse { + display: none; + } + } +`; + +/* Styles applied only to ads within an article inserted by spacefinder */ +const articleAdSlotStyles = css` + ${inlineAdSlotContainerStyles} + + /* Give ad slots inserted on the client side a placeholder height. + Let the ad slot take control of its height once rendered. */ + .ad-slot--inline:not(.ad-slot--rendered) { + min-height: ${adSizes.outstreamMobile.height + + constants.AD_LABEL_HEIGHT}px; + + ${from.desktop} { + min-height: ${adSizes.mpu.height + constants.AD_LABEL_HEIGHT}px; + } + } + + /* Give inline1 ad slot a different placeholder height comparing to subsequent-inlines to reduce CLS. + Let the ad slot take control of its height once rendered. + IMPORTANT NOTE: We currently do not serve OPT-OUT for inline1 but we will need to change this value before we do. */ + .ad-slot--inline1:not(.ad-slot--rendered) { + ${from.desktop} { + min-height: ${adSizes.outstreamDesktop.height + + constants.AD_LABEL_HEIGHT}px; + } + } + + /* This refers to the inline top-above-nav slot used on mobile pages, NOT the + top-above-nav that is inserted above the navigation. */ + .ad-slot--top-above-nav:not(.ad-slot--rendered) { + ${until.tablet} { + min-height: ${adSizes.outstreamMobile.height + + constants.AD_LABEL_HEIGHT}px; + } + } + + .ad-slot--carrot { + float: left; + clear: both; + width: 140px; + margin-right: 20px; + margin-bottom: ${space[1]}px; + ${from.leftCol} { + position: relative; + margin-left: -160px; + width: 140px; + } + ${from.wide} { + margin-left: -240px; + width: 220px; + } + } + + /* Scroll for more label on interscrollers */ + .ad-slot__scroll { + position: fixed; + bottom: 0; + width: 100%; + + ${labelBoxStyles} + + &.visible { + visibility: initial; + } + &.hidden { + visibility: hidden; + } + } + + .ad-slot--interscroller[data-label-show='true']::before { + content: 'Advertisement'; + position: absolute; + top: 0; + left: 0; + right: 0; + border: 0; + display: block; + ${labelBoxStyles} + } +`; + +/* Styles applied to all ads regardless of their position */ +const rootAdStyles = [labelStyles, adSlotStyles, adSlotContainerStyles]; + +export { + labelHeight, + // adSlotContainerStyles, + adSlotStyles, + articleAdSlotStyles, + labelStyles, + adContainerCentreSlotStyles, + // adContainerStyles, + rootAdStyles, +}; diff --git a/dotcom-rendering/src/lib/rootStyles.ts b/dotcom-rendering/src/lib/rootStyles.ts index 58f2d374bae..fbf3baa1270 100644 --- a/dotcom-rendering/src/lib/rootStyles.ts +++ b/dotcom-rendering/src/lib/rootStyles.ts @@ -4,6 +4,7 @@ import { palette as sourcePalette, } from '@guardian/source/foundations'; import { paletteDeclarations } from '../palette'; +import { rootAdStyles } from './adStyles'; import type { ArticleFormat } from './articleFormat'; /** @@ -49,8 +50,5 @@ export const rootStyles = ( color: ${sourcePalette.neutral[7]}; } - .ad-slot-container { - /* prevent third-party code from breaking our layout */ - max-width: 100vw; - } + ${rootAdStyles} `;