diff --git a/files/en-us/web/css/reference/properties/scroll-padding/index.md b/files/en-us/web/css/reference/properties/scroll-padding/index.md index cf38fb206f9f350..7cc7c27fde4c8b3 100644 --- a/files/en-us/web/css/reference/properties/scroll-padding/index.md +++ b/files/en-us/web/css/reference/properties/scroll-padding/index.md @@ -6,7 +6,7 @@ browser-compat: css.properties.scroll-padding sidebar: cssref --- -The **`scroll-padding`** [shorthand property](/en-US/docs/Web/CSS/Guides/Cascade/Shorthand_properties) sets scroll padding on all sides of an element at once, much like the {{cssxref("padding")}} property does for padding on an element. +The **`scroll-padding`** [shorthand property](/en-US/docs/Web/CSS/Guides/Cascade/Shorthand_properties) sets scroll padding on all sides of an element at once. It specifies offsets that define the optimal viewing region of a scrollport within a {{glossary("scroll container")}}. {{InteractiveExample("CSS Demo: scroll-padding")}} @@ -19,7 +19,7 @@ scroll-padding: 20px; ``` ```css interactive-example-choice -scroll-padding: 2em; +scroll-padding: 20%; ``` ```html interactive-example @@ -70,8 +70,6 @@ scroll-padding: 2em; } ``` -The `scroll-padding-*` properties define offsets for the _optimal viewing region_ of the scrollport: the region used as the target region for placing things in view of the user. This allows the author to exclude regions of the scrollport that are obscured by other content (such as fixed-positioned toolbars or sidebars), or to put more breathing room between a targeted element and the edges of the scrollport. - ## Constituent properties This property is a shorthand for the following CSS properties: @@ -107,6 +105,14 @@ scroll-padding: unset; - `auto` - : The offset is determined by the user agent. This will generally be `0px`, but the user agent is free to detect and do something else if a non-zero value is more appropriate. +## Description + +The `scroll-padding` property is a shorthand that sets {{CSSXref("scroll-padding-top")}}, {{CSSXref("scroll-padding-right")}}, {{CSSXref("scroll-padding-bottom")}}, and {{CSSXref("scroll-padding-left")}}, in that order, setting the top, right, bottom, and left scroll padding of a scroll container, respectively. + +Useful when creating scroll-snap containers, the `scroll-padding` property enables defining offsets for the _optimal viewing region_ of the scrollport: the region used as the target region for placing elements in view of the user. This allows you to create insets in the scrollport to make room for objects that might obscure the content, such as fixed-positioned toolbars or sidebars, or to put more breathing room between a targeted element and the edges of the scrollport. + +While defined in the [CSS scroll snap](/en-US/docs/Web/CSS/Guides/Scroll_snap) module, this property applies to all scroll containers, no matter the value of the {{cssxref("scroll-snap-type")}} property. + ## Formal definition {{cssinfo}} @@ -125,5 +131,8 @@ scroll-padding: unset; ## See also -- [CSS scroll snap](/en-US/docs/Web/CSS/Guides/Scroll_snap) -- [Well-controlled scrolling with CSS scroll snap](https://web.dev/articles/css-scroll-snap) +- {{cssxref("scroll-snap-type")}} +- [Basic concepts of scroll-snap](/en-US/docs/Web/CSS/Guides/Scroll_snap/Basic_concepts) +- [CSS scroll snap](/en-US/docs/Web/CSS/Guides/Scroll_snap) module +- [CSS overflow](/en-US/docs/Web/CSS/Guides/Overflow) module +- [CSS scroll-driven animations](/en-US/docs/Web/CSS/Guides/Scroll-driven_animations) module diff --git a/scripts/analyze-pr-build.js b/scripts/analyze-pr-build.js index c180b56670affcb..ebb293051231a3f 100644 --- a/scripts/analyze-pr-build.js +++ b/scripts/analyze-pr-build.js @@ -18,6 +18,10 @@ const MAX_COMMENT_BODY_LENGTH = 65000; const hiddenCommentRegex = //; +/** + * @import { Doc } from "@mdn/rari" + */ + /** * Main function to analyze a PR build directory and post (or print) a comment. * @param {string} buildDirectory - Path to the build directory. @@ -25,14 +29,15 @@ const hiddenCommentRegex = */ async function analyzePR(buildDirectory, config) { const combinedComments = []; + const docs = await getBuiltDocs(buildDirectory); if (config.prefix) { - const deploymentComment = await postAboutDeployment(buildDirectory, config); + const deploymentComment = postAboutDeployment(docs, config); if (deploymentComment) combinedComments.push(deploymentComment); } if (config.analyze_flaws) { - const flawsComment = await postAboutFlaws(buildDirectory, config); + const flawsComment = postAboutFlaws(docs, config); if (flawsComment) combinedComments.push(flawsComment); } @@ -47,11 +52,7 @@ async function analyzePR(buildDirectory, config) { console.error(`Error reading diff file: ${err}`); } } - const dangerousComment = await postAboutDangerousContent( - buildDirectory, - patch, - config, - ); + const dangerousComment = postAboutDangerousContent(docs, patch, config); if (dangerousComment) combinedComments.push(dangerousComment); } @@ -137,13 +138,30 @@ function truncateComment(comment) { return comment; } +/** + * Formats a section with a heading, collapsed by default unless expanded is set. + * @param {object} options - Formatting options. + * @param {string} options.title - The section title (e.g., "Preview URLs", "Flaws"). + * @param {number} options.count - The count to display in parentheses. + * @param {string} [options.countLabel] - Optional label after count (e.g., "pages"). + * @param {string} options.body - The section content. + * @param {boolean} [options.expanded] - If true, show expanded (no details wrapper). + */ +function formatSection({ title, count, countLabel, body, expanded }) { + const countText = countLabel ? `${count} ${countLabel}` : count; + const header = `${title} (${countText})`; + if (expanded) { + return `${header}\n\n${body}`; + } + return `
${header}\n\n${body}\n\n
`; +} + /** * Constructs a comment about the deployment with preview URLs. - * @param {string} buildDirectory - Path to the build directory. + * @param {Doc[]} docs - Array of built document objects. * @param {object} config - Configuration object. */ -async function postAboutDeployment(buildDirectory, config) { - const docs = await getBuiltDocs(buildDirectory); +function postAboutDeployment(docs, config) { let links = []; for (const doc of docs) { if (doc.mdn_url) { @@ -155,13 +173,13 @@ async function postAboutDeployment(buildDirectory, config) { links.sort(); if (links.length > 0) { - if (links.length > 5) { - const heading = `
Preview URLs (${links.length} pages)\n\n`; - return heading + links.join("\n") + "\n\n
"; - } else { - const heading = `Preview URLs\n\n`; - return heading + links.join("\n"); - } + return formatSection({ + title: "Preview URLs", + count: links.length, + countLabel: links.length == 1 ? "page" : "pages", + body: links.join("\n"), + expanded: links.length <= 5, + }); } return "*seems not a single file was built!* 🙀"; } @@ -178,13 +196,12 @@ function mdnUrlToDevUrl(prefix, host, mdnUrl) { /** * Constructs a comment reporting any dangerous external URLs. - * @param {string} buildDirectory - Path to the build directory. + * @param {Doc[]} docs - Array of built document objects. * @param {Array} patch - Array of patch objects (from parse-diff). * @param {object} config - Configuration object. */ -async function postAboutDangerousContent(buildDirectory, patch, config) { +function postAboutDangerousContent(docs, patch, config) { const OK_URL_PREFIXES = ["https://github.com/mdn/"]; - const docs = await getBuiltDocs(buildDirectory); const comments = []; let totalUrls = 0; @@ -286,11 +303,10 @@ async function postAboutDangerousContent(buildDirectory, patch, config) { /** * Constructs a comment reporting document flaws. - * @param {string} buildDirectory - Path to the build directory. + * @param {Doc[]} docs - Array of built document objects. * @param {object} config - Configuration object. */ -async function postAboutFlaws(buildDirectory, config) { - const docs = await getBuiltDocs(buildDirectory); +function postAboutFlaws(docs, config) { const comments = []; const MAX_FLAW_EXPLANATION = 5; let docsWithZeroFlaws = 0; @@ -359,17 +375,30 @@ async function postAboutFlaws(buildDirectory, config) { lines.push(comment); perDocComments.push(lines.join("\n")); } - let heading = `\n
Flaws (${totalFlaws})\n\n`; - if (docsWithZeroFlaws) { - heading += `Note! *${docsWithZeroFlaws} document${docsWithZeroFlaws === 1 ? "" : "s"} with no flaws that don't need to be listed. 🎉*\n\n`; - } - return heading + perDocComments.join("\n\n---\n\n") + "\n\n
"; + const zeroFlawsNote = docsWithZeroFlaws + ? `Note! *${docsWithZeroFlaws} document${docsWithZeroFlaws === 1 ? "" : "s"} with no flaws that don't need to be listed. 🎉*\n\n` + : ""; + + const reportIssueNote = + "*Found an unexpected or unresolvable flaw? [Please report it here](https://github.com/mdn/rari/issues/new?template=bug.yml).*\n\n"; + + return ( + "\n" + + formatSection({ + title: "Flaws", + count: totalFlaws, + body: + zeroFlawsNote + reportIssueNote + perDocComments.join("\n\n---\n\n"), + expanded: docs.length <= 5 || totalFlaws <= 5, + }) + ); } } /** * Recursively finds and returns the parsed JSON document objects from all index.json files. * @param {string} buildDirectory - Path to the build directory. + * @returns {Doc[]} */ async function getBuiltDocs(buildDirectory) { const docs = [];