diff --git a/docs/explanations/architecture/assets/global-styles-input-output.excalidraw b/docs/explanations/architecture/assets/global-styles-input-output.excalidraw new file mode 100644 index 0000000000000..5257050084346 --- /dev/null +++ b/docs/explanations/architecture/assets/global-styles-input-output.excalidraw @@ -0,0 +1,922 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "rectangle", + "version": 69, + "versionNonce": 1371893668, + "isDeleted": false, + "id": "dE1I-EnEvkRXGzhdq1JtQ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 460, + "y": 200, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 180, + "height": 100, + "seed": 1590887460, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "whcfsZ0hp0-cjJAqlj0ob", + "type": "arrow" + }, + { + "id": "sL5M8MOmbWBPiIMWJPKAv", + "type": "arrow" + }, + { + "id": "iOHR_Txg1Rt_gfJPeXqZg", + "type": "arrow" + }, + { + "id": "yLz66yM1_qJAWngBli08H", + "type": "arrow" + } + ], + "updated": 1643633406183 + }, + { + "type": "text", + "version": 153, + "versionNonce": 670281809, + "isDeleted": false, + "id": "5rFvoYoEiSaqNhwmlPjxf", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 500, + "y": 220, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 106, + "height": 51, + "seed": 1103877284, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643794034400, + "fontSize": 20, + "fontFamily": 1, + "text": "WordPress'\ntheme.json", + "baseline": 44, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "WordPress'\ntheme.json" + }, + { + "type": "rectangle", + "version": 61, + "versionNonce": 47826468, + "isDeleted": false, + "id": "otWLW4l8pmq6prNMU4yVj", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 700, + "y": 200, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 160, + "height": 100, + "seed": 1273608996, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "yLz66yM1_qJAWngBli08H", + "type": "arrow" + } + ], + "updated": 1643633405414 + }, + { + "type": "text", + "version": 128, + "versionNonce": 1069768604, + "isDeleted": false, + "id": "r1nDCG4qF6PJ6TXDA8D0W", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 720, + "y": 220, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 100, + "height": 51, + "seed": 217970972, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "yLz66yM1_qJAWngBli08H", + "type": "arrow" + } + ], + "updated": 1643633404909, + "fontSize": 20, + "fontFamily": 1, + "text": "theme's\ntheme.json", + "baseline": 44, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "theme's\ntheme.json" + }, + { + "type": "rectangle", + "version": 161, + "versionNonce": 516967708, + "isDeleted": false, + "id": "uyFiLHMSH6y7H-s3quAxV", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 920, + "y": 40, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 200, + "height": 80, + "seed": 412676132, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "rAP823QGa675R6VNN5_Fj", + "type": "arrow" + }, + { + "id": "zqYpQBYVH8MUQ1gbny0DW", + "type": "arrow" + }, + { + "id": "bZAzg4sYJCkziajbnNelc", + "type": "arrow" + }, + { + "id": "Gf8rkiJMUzlf_neDMa8Uo", + "type": "arrow" + } + ], + "updated": 1643633370772 + }, + { + "type": "text", + "version": 252, + "versionNonce": 788243108, + "isDeleted": false, + "id": "2fO2-BoHTfIU44g9j0n-S", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 940, + "y": 60, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 165, + "height": 51, + "seed": 231248924, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "Gf8rkiJMUzlf_neDMa8Uo", + "type": "arrow" + }, + { + "id": "RXAV87dIe7h-TdMpPkj8G", + "type": "arrow" + } + ], + "updated": 1643633370772, + "fontSize": 20, + "fontFamily": 1, + "text": "Global styles UI\nin site editor", + "baseline": 44, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Global styles UI\nin site editor" + }, + { + "type": "rectangle", + "version": 85, + "versionNonce": 1702175071, + "isDeleted": false, + "id": "hewO7U2_RQB8vdU_-mPPB", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 580, + "y": 660, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 340, + "height": 100, + "seed": 726898972, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "ccK0gnrFParTub-zbOTR2", + "type": "arrow" + }, + { + "id": "eP2wDSsiTc_n6dPEvV37C", + "type": "arrow" + } + ], + "updated": 1643794081747 + }, + { + "type": "text", + "version": 117, + "versionNonce": 581323025, + "isDeleted": false, + "id": "eU8Kg0BNmsuuDOweR3g88", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 660, + "y": 700, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 215, + "height": 26, + "seed": 404952740, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643794068178, + "fontSize": 20, + "fontFamily": 1, + "text": "global-styles-inline-css", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "global-styles-inline-css" + }, + { + "type": "text", + "version": 13, + "versionNonce": 1960935025, + "isDeleted": false, + "id": "CnDgoEZ_UKEJ24A9Y8p-H", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 597, + "y": 667, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38, + "height": 26, + "seed": 2110409124, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643794076348, + "fontSize": 20, + "fontFamily": 1, + "text": "CSS", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "CSS" + }, + { + "type": "rectangle", + "version": 134, + "versionNonce": 827573105, + "isDeleted": false, + "id": "ymhNrWoCwMcy97bV3wcKR", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 480, + "y": 440, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 600.0000000000001, + "height": 60, + "seed": 856798492, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "rAP823QGa675R6VNN5_Fj", + "type": "arrow" + }, + { + "id": "zqYpQBYVH8MUQ1gbny0DW", + "type": "arrow" + }, + { + "id": "whcfsZ0hp0-cjJAqlj0ob", + "type": "arrow" + }, + { + "id": "bZAzg4sYJCkziajbnNelc", + "type": "arrow" + }, + { + "id": "sL5M8MOmbWBPiIMWJPKAv", + "type": "arrow" + }, + { + "id": "3BPPljmfDBwi9j0UFo72A", + "type": "arrow" + }, + { + "id": "iOHR_Txg1Rt_gfJPeXqZg", + "type": "arrow" + }, + { + "id": "Vb1dPpA_zGw4ibPc2H8XD", + "type": "arrow" + }, + { + "id": "4EUXGzEm8Fy3BBuebotFc", + "type": "arrow" + }, + { + "id": "celRUoUyUQIT-gGhAXyEK", + "type": "arrow" + }, + { + "id": "yLz66yM1_qJAWngBli08H", + "type": "arrow" + } + ], + "updated": 1643794050979 + }, + { + "type": "arrow", + "version": 761, + "versionNonce": 2121815743, + "isDeleted": false, + "id": "Vb1dPpA_zGw4ibPc2H8XD", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 779.6809331076444, + "y": 299.60856638674625, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.816506265121575, + "height": 132.78830939921954, + "seed": 1207657756, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643794051290, + "startBinding": null, + "endBinding": { + "elementId": "ymhNrWoCwMcy97bV3wcKR", + "gap": 7.603124214034267, + "focus": 0.010960154267448993 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 2.816506265121575, + 132.78830939921954 + ] + ] + }, + { + "type": "line", + "version": 116, + "versionNonce": 2071091108, + "isDeleted": false, + "id": "uIhYulJsyst7aUpzTX4go", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 340.5942201212048, + "y": 361.19947067946197, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 916.0579537755439, + "height": 0, + "seed": 1575735580, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643633370772, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 916.0579537755439, + 0 + ] + ] + }, + { + "type": "text", + "version": 57, + "versionNonce": 1217366463, + "isDeleted": false, + "id": "siLfF4byWfGnkekw1DNmu", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 380, + "y": 40, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68, + "height": 26, + "seed": 941782436, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643794093388, + "fontSize": 20, + "fontFamily": 1, + "text": "INPUT", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "INPUT" + }, + { + "type": "line", + "version": 155, + "versionNonce": 571458340, + "isDeleted": false, + "id": "2EOVSOSu-XvcXmsarGRNX", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 340.31421109884974, + "y": 599.7727356031537, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 916.0579537755439, + "height": 0, + "seed": 482945060, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643633370772, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 916.0579537755439, + 0 + ] + ] + }, + { + "type": "text", + "version": 65, + "versionNonce": 438071580, + "isDeleted": false, + "id": "iqUBVRUA4jHj817dlF-oa", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 360, + "y": 640, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 89, + "height": 26, + "seed": 578631196, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643633370772, + "fontSize": 20, + "fontFamily": 1, + "text": "OUTPUT", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "OUTPUT" + }, + { + "type": "text", + "version": 160, + "versionNonce": 2029239972, + "isDeleted": false, + "id": "2Zb3N-iXP0MEwBqCay37k", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 520, + "y": 460, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 505, + "height": 26, + "seed": 934136228, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643633370772, + "fontSize": 20, + "fontFamily": 1, + "text": "Internal Representation (WP_Theme_JSON object)", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Internal Representation (WP_Theme_JSON object)" + }, + { + "type": "arrow", + "version": 694, + "versionNonce": 1024752273, + "isDeleted": false, + "id": "celRUoUyUQIT-gGhAXyEK", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 779.718628924312, + "y": 501, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 1.0791064091945373, + "height": 126.66251027234523, + "seed": 2100655268, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643794051290, + "startBinding": { + "elementId": "ymhNrWoCwMcy97bV3wcKR", + "gap": 1, + "focus": 0.0018167083707156541 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 1.0791064091945373, + 126.66251027234523 + ] + ] + }, + { + "type": "rectangle", + "version": 179, + "versionNonce": 1901269284, + "isDeleted": false, + "id": "4IJppZHOQRDTcVw-pjt1z", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 920, + "y": 200, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 180, + "height": 100, + "seed": 1157165980, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "rAP823QGa675R6VNN5_Fj", + "type": "arrow" + }, + { + "id": "zqYpQBYVH8MUQ1gbny0DW", + "type": "arrow" + }, + { + "id": "bZAzg4sYJCkziajbnNelc", + "type": "arrow" + }, + { + "id": "3BPPljmfDBwi9j0UFo72A", + "type": "arrow" + }, + { + "id": "4EUXGzEm8Fy3BBuebotFc", + "type": "arrow" + }, + { + "id": "Gf8rkiJMUzlf_neDMa8Uo", + "type": "arrow" + }, + { + "id": "RXAV87dIe7h-TdMpPkj8G", + "type": "arrow" + } + ], + "updated": 1643633370772 + }, + { + "type": "text", + "version": 289, + "versionNonce": 880880164, + "isDeleted": false, + "id": "CA1UwOP4UrmE6pla-3RZT", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 960, + "y": 220, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 100, + "height": 51, + "seed": 1509336100, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "RXAV87dIe7h-TdMpPkj8G", + "type": "arrow" + } + ], + "updated": 1643633398374, + "fontSize": 20, + "fontFamily": 1, + "text": "user's\ntheme.json", + "baseline": 44, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "user's\ntheme.json" + }, + { + "type": "text", + "version": 84, + "versionNonce": 773068836, + "isDeleted": false, + "id": "loyhrrk-dULHcklwEwSld", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 360, + "y": 380, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 118, + "height": 26, + "seed": 1415224092, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1643633370773, + "fontSize": 20, + "fontFamily": 1, + "text": "INTERNALS", + "baseline": 18, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "INTERNALS" + }, + { + "type": "arrow", + "version": 878, + "versionNonce": 400369375, + "isDeleted": false, + "id": "4EUXGzEm8Fy3BBuebotFc", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1020.5557521929989, + "y": 301, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0.8847309846728422, + "height": 129, + "seed": 1086156700, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643794051290, + "startBinding": { + "elementId": "4IJppZHOQRDTcVw-pjt1z", + "gap": 1, + "focus": -0.12071261013586085 + }, + "endBinding": { + "elementId": "ymhNrWoCwMcy97bV3wcKR", + "gap": 10.000000000000002, + "focus": 0.7974420373674143 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -0.8847309846728422, + 129 + ] + ] + }, + { + "type": "arrow", + "version": 20, + "versionNonce": 39323804, + "isDeleted": false, + "id": "RXAV87dIe7h-TdMpPkj8G", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1020.9070453807711, + "y": 120.28604858589358, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0.9070453807711374, + "height": 59.71395141410642, + "seed": 748070564, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643633370773, + "startBinding": { + "elementId": "2fO2-BoHTfIU44g9j0n-S", + "focus": 0.012843458210903786, + "gap": 9.286048585893582 + }, + "endBinding": { + "elementId": "4IJppZHOQRDTcVw-pjt1z", + "focus": 0.09846585725336464, + "gap": 20 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -0.9070453807711374, + 59.71395141410642 + ] + ] + }, + { + "type": "arrow", + "version": 897, + "versionNonce": 44630129, + "isDeleted": false, + "id": "yLz66yM1_qJAWngBli08H", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 540.1474954442242, + "y": 301, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 3.013965627388984, + "height": 131.59259259259267, + "seed": 1185633948, + "groupIds": [], + "strokeSharpness": "round", + "boundElements": [], + "updated": 1643794051290, + "startBinding": { + "elementId": "dE1I-EnEvkRXGzhdq1JtQ", + "gap": 1, + "focus": 0.1209125431173364 + }, + "endBinding": { + "elementId": "ymhNrWoCwMcy97bV3wcKR", + "gap": 7.407407407407392, + "focus": -0.7848083884682261 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 3.013965627388984, + 131.59259259259267 + ] + ] + } + ], + "appState": { + "gridSize": 20, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/explanations/architecture/assets/global-styles-input-output.png b/docs/explanations/architecture/assets/global-styles-input-output.png new file mode 100644 index 0000000000000..ecfcdc6b8124d Binary files /dev/null and b/docs/explanations/architecture/assets/global-styles-input-output.png differ diff --git a/docs/explanations/architecture/key-concepts.md b/docs/explanations/architecture/key-concepts.md index 1df4cea5b2325..fba75ab92f946 100644 --- a/docs/explanations/architecture/key-concepts.md +++ b/docs/explanations/architecture/key-concepts.md @@ -57,6 +57,8 @@ While the post editor concentrates on the content of a post, the [template](/doc Note: custom post types can also be initialized with a starting `post_content` template that should not be confused with the theme template system described above. -## Global Styles (in progress) +## Global Styles -Describes a set of configuration and default properties of blocks and their visual aspects. Global Styles is both an interface (which users access through the site editor) and a configuration system done through [a `theme.json` file](/docs/how-to-guides/themes/theme-json.md). This file absorbs most of the configuration aspects usually scattered through various `add_theme_support` calls to simplify communicating with the editor. It thus aims to improve declaring what settings should be enabled, what attributes are supported, what specific tools a theme offers (like a custom color palette), the available design tools present both globally and on each block, and an infrastructure that allows to enqueue only the relevant CSS based on what blocks are used on a page. +Global Styles is both an interface (which users access through the site editor) and a configuration system done through [a `theme.json` file](/docs/how-to-guides/themes/theme-json.md). This file absorbs most of the configuration aspects usually scattered through various `add_theme_support` calls to simplify communicating with the editor. It thus aims to improve declaring what settings should be enabled, what specific tools a theme offers (like a custom color palette), the available design tools present, and an infrastructure that allows to coordinate the styles coming from WordPress, the active theme, and the user. + +Learn more about [Global Styles](/docs/explanations/architecture/styles.md#global-styles). diff --git a/docs/explanations/architecture/styles.md b/docs/explanations/architecture/styles.md new file mode 100644 index 0000000000000..060c6b4c4e5c2 --- /dev/null +++ b/docs/explanations/architecture/styles.md @@ -0,0 +1,457 @@ +## Styles in the block editor + +This document introduces the main concepts related to styles that affect the user content in the block editor. It points to the relevant reference guides and tutorials for readers to dig deeper into each one of the ideas presented. It's aimed to block authors and people working in the block editor project. + +1. HTML and CSS +2. Block styles + - From UI controls to HTML markup + - Block Supports API + - Current limits of the Block Supports API +3. Global styles + - Gather data + - Consolidate data + - From data to styles + - Current limits of the Global styles API + +### HTML and CSS + +By creating a post in the block editor the user is creating a number of artifacts: a HTML document plus a number of CSS stylesheets, either embedded in the document or external. + +The final HTML document is the result of a few things: + +- the [WordPress templates](https://developer.wordpress.org/themes/basics/template-files/) provided by the theme, either via PHP (classic theme) or via HTML templates (block theme) ([learn more](https://developer.wordpress.org/themes/block-themes/#differences-and-similarities-between-classic-themes-and-block-themes) about the differences) +- the [blocks](https://developer.wordpress.org/block-editor/reference-guides/core-blocks/) and patterns in use that come with a predefined structure (HTML markup) +- the user modifications to the content: adding content, transforming existing content (convert a given paragraph into a heading), or modifying it (attaching a class or inline styles to a block) + +The stylesheets loaded in the front end include: + +- **Blocks**. The stylesheets that come with the block. In the front end, you can find a single stylesheet with all block styles defined by WordPress (`wp-block-library-*` ) or separate stylesheets per block in use (as in `wp-block-group-*`, `wp-block-columns-*`, etc). See [this note](https://make.wordpress.org/core/2021/07/01/block-styles-loading-enhancements-in-wordpress-5-8/) for the full details. +- **Global styles**. These styles are generated on the fly by using data coming from a theme.json file: see [note](https://make.wordpress.org/core/2021/06/25/introducing-theme-json-in-wordpress-5-8/), [reference](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/), and [how to guide](https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/). Specifically, it merges the contents of the theme.json from WordPress, the theme.json from the theme (if it has one), and the user data provided via the global styles sidebar in the site editor. The result of processing this data is an embedded stylesheet whose id is `global-styles-inline-css`. +- **Theme**. Historically, themes have enqueued their own stylesheets, where the id is based on the theme name, as in `twentytwentytwo-style-css`. In addition to having their own stylesheets they can now declare a theme.json file containing styles that will be part of the stylesheet generated by global styles. +- **User**. Some of the user actions in the editor will generate style content. This is the case for features such as duotone, layout, or link color. +- **Other**. WordPress and plugins can also enqueue stylesheets. + +### Block styles + +Since the introduction of the block editor in WordPress 5.0, there were tools for the users to "add styles" to specific blocks. By using these tools, the user would attach new classes or inline styles to the blocks, modifying their visual aspect. + +By default, blocks come with a given HTML markup. Think of the paragraph block, for example: + +```html +

+``` + +In its simplest form, any style rule that targets the `p` selector will apply styles to this block, whether it comes from a block, a theme, etc. + +The user may change the state of this block by applying different styles: a text alignment, a color, a font size, a line height, etc. These states are reflected in the HTML markup of the block in the form of HTML attributes, mainly through the `class` or `style` attributes, though it can be any other the block author sees fit. + +After some user modifications to the block, the initial markup may become something like this: + +```html +

+``` + +This is what we refer to as "user-provided block styles", also know as "local styles" or "serialized styles". Essentially, each tool (font size, color, etc) ends up adding some classes and/or inline styles to the block markup. The CSS styling for these classes is part of the block, global, or theme stylesheets. + +The ability to modify a block state coupled with the fact that a block can live within any other block (think of a paragraph within a group), creates a vast amount of potential states and style possibilities. + +#### From UI controls to HTML markup + +If you follow the [block tutorial](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/) you can learn up about the different parts of the [block API](https://developer.wordpress.org/block-editor/reference-guides/block-api/) presented here in more detail and also build your own block. This is an introduction to the general concepts of how a block can let users edit its state. + +To build an experience like the one described above a block author needs a few pieces: + +1. **A UI control**. It presents the user some choices, for example, to be able to change the font size of the block. The control takes care of reading the data from the block (does this block already have a font size assigned?) and other data it needs (what are the font sizes a user can use in this block?). See available [component library](https://developer.wordpress.org/block-editor/reference-guides/components/). +2. **A block attribute**. The block needs to hold data to know which modifications were applied to it: whether it has been given a font size already for example. See how blocks can define [attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/). +3. **Access to style data**. A control may need external information about the styles available for a given block: the list of colors, or the list of font sizes, for example. These are called "style presets", as they are a preselection of styles usually defined by the theme, although WordPress provides some defaults. Check the [list of data](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/#settings) a theme can provide to the editor and how a block author can get access to it via [useSetting](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#usesetting). +4. **Serialize the user style into HTML markup**. Upon a user action, the block HTML markup needs to be updated accordingly (apply the proper class or inline style). This process is called serialization and it is the [edit, save](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/), and [render_callback](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/creating-dynamic-blocks/) functions' responsibility: these functions take block data and convert it into HTML. + +In essence, these are the essential mechanics a block author needs to care about for their block to be able to be styled by the user. While this can be done completely manually, there's an API that automates this process for common style needs: block supports. + +#### Block Supports API + +[Block Supports](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/) is an API that allows a block to declare what features it supports. By adding some info to their [block.json file](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/), the block tells the system what kind of actions a user can do to it. + +For example: + +```json +{ + "name": "core/paragraph", + "...": "...", + "supports": { + "typography": { + "fontSize": true + } + } +} +``` + +The paragraph declares support for font size in its `block.json`. This means the block will show a UI control for users to tweak its font size, unless it's disabled by the theme (learn more about how themes can disable UI controls in [the `theme.json` reference](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/)). The system will also take care of setting up the UI control data (the font size of the block if it has one already assigned, the list of available font sizes to show), and will serialize the block data into HTML markup upon user changes (attach classes and inline styles appropriately). + +By using the block supports mechanism via `block.json`, the block author is able to create the same experience as before just by writing a couple of lines. Check the tutorials for adding block supports to [static](/docs/how-to-guides/block-tutorial/block-supports-in-static-blocks.md) and [dynamic](/docs/how-to-guides/block-tutorial/block-supports-in-dynamic-blocks.md) blocks. + +Besides the benefit of having to do less work to achieve the same results, there's a few other advantages: + +- the style information of the block becomes available for the native mobile apps and in the server +- the block will use the UI controls other blocks use for the same styles, creating a more coherent user experience +- the UI controls in use by the block will be automatically updated as they are improved, without the block author having to do anything + +#### Current limitations of the Block Supports API + +While the Block Supports API provides value, it also comes with some limitations a block author needs to be aware of. To better visualize what they are, let's run with the following example of a table block: + +```html + + + + + + + + + +
Header
First
Second
Footer
+``` + +1. **Only one style type per block.** + +One of the limitations is that, from all the [styles available](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/), there can be only one instance of any them in use by the block. Following the example, the table block can only have a single font size. If the block author wanted to have three different font sizes (head, body, and footer) it can't do it using the current block supports API. See [this issue](https://github.com/WordPress/gutenberg/issues/33255) for more detailed info and ways forward. + +2. **Styles are serialized to the outermost HTML node of the block, the wrapper.** + +The block supports API only serializes the font size value to the wrapper, resulting in the following HTML `` . The current block supports API doesn't serialize this value to a different node, for example, the ``. + +This is an active area of work you can follow [in the tracking issue](https://github.com/WordPress/gutenberg/issues/38167). The linked proposal is exploring a different way to serialize the user changes: instead of each block support serializing its own data (for example, classes such as `has-small-font-size`, `has-green-color`) the idea is the block would get a single class instead (for example, `wp-style-UUID`) and the CSS styling for that class will be generated in the server by WordPress. + +While work continues in that proposal, there's an escape hatch, an experimental option block authors can use. Any block support can skip the serialization to HTML markup by using `__experimentalSkipSerialization`. For example: + +```json +{ + "name": "core/paragraph", + "...": "...", + "supports": { + "typography": { + "fontSize": true, + "__experimentalSkipSerialization": true + } + } +} +``` + +This means that the typography block support will do all of the things (create a UI control, bind the block attribute to the control, etc) except serializing the user values into the HTML markup. The classes and inline styles will not be automatically applied to the wrapper and it is the block author's responsibility to implement this in the `edit`, `save`, and `render_callback` functions. See [this issue](https://github.com/WordPress/gutenberg/issues/28913) for examples of how it was done for some blocks provided by WordPress. + +Note that, once `__experimentalSkipSerialization` is enabled for a group (typography, color, spacing) it affects all block supports within this group (font size, line height, and font family within typography, and so on). There's [ongoing work](https://github.com/WordPress/gutenberg/pull/36293) to be able to disable block supports individually, you can follow that issue to check the status. + +### Global styles + +Global Styles refers to a mechanism that generates site-wide styles. Unlike the block styles described in the previous section, these are not serialized into the post content and are not attached to the block HTML. Instead, the output of this system is a new stylesheet with id `global-styles-inline-css`. + +This mechanism was [introduced in WordPress 5.8](https://make.wordpress.org/core/2021/06/25/introducing-theme-json-in-wordpress-5-8/). At the time, it only took data from WordPress and the active theme. WordPress 5.9 expanded the system to also take style data from users. + +This is the general data flow: + +![global-styles-input-output](./assets/global-styles-input-output.png) + +The process of generating the stylesheet has, in essence, three steps: + +1. Gather data: the `theme.json` file [bundled with WordPress](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/theme.json), the `theme.json` file of the active theme if it exists, and the user's styles provided via the global styles UI in the site editor. +2. Consolidate data: the structured information from different origins -WordPress defaults, theme, and user- is normalized and merged into a single structure. +3. Convert data into a stylesheet: convert the internal representation into CSS style rules and enqueue them as a stylesheet. + +#### Gather data + +The data can come from three different origins: WordPress defaults, the active theme, or the user. All three of them use the same [`theme.json` format](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/). + + Data from WordPress and the active theme is retrieved from the corresponding `theme.json` file. Data from the user is pulled from the database, where it's stored after the user saves the changes they did via the global styles sidebar in the site editor. + +#### Consolidate data + +The goal of this phase is to build a consolidated structure. + +There are two important processes going on in this phase. First, the system needs to normalize all the incoming data, as different origins may be using different versions of the `theme.json` format. For example, a theme may be using [v1](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-v1/) while the WordPress base is using [the latest version](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/). Second, the system needs to decide how to merge the input into a single structure. This will be the focus of the following sections. + +##### Styles + +Different parts of the incoming `theme.json` structure are treated differently. The data present in the `styles` section is blended together following this logic: user data overrides theme data, and theme data overrides WordPress data. + +For example, if we had the following three `theme.json` structures coming from WordPress, the theme, and the user respectively: + +```json +{ + "styles": { + "color": { + "background": "" + }, + "typography": { + "fontSize": "" + } + } +} +``` + +```json +{ + "styles": { + "typography": { + "fontSize": "", + "lineHeight": "" + } + } +} +``` + +```json +{ + "styles": { + "typography": { + "lineHeight": "" + } + } +} +``` + +The result after the consolidation would be: + +```json +{ + "styles": { + "color": { + "background": "" + }, + "typography": { + "fontSize": "", + "lineHeight": "" + } + } +} +``` + +##### Settings + +The `settings` section works differently than styles. Most of the settings are only used to configure the editor and have no effect on the global styles. Only a few of them are part of the resulting stylesheet: the presets. + +Presets are the predefined styles that are shown to the user in different parts of the UI: the color palette or the font sizes, for example. They comprise the following settings: `color.duotone`, `color.gradients`, `color.palette`, `typography.fontFamilies`, `typography.fontSizes`. Unlike `styles`, presets from an origin don't override values from other origins. Instead, all of them are stored in the consolidated structure. + +For example, if we have the following `theme.json` structures coming from WordPress, the theme, and the user respectively: + +```json +{ + "settings": { + "color": { + "palette": [ "" ], + "gradients": [ "" ] + } + } +} +``` + +```json +{ + "settings": { + "color": { + "palette": [ "" ] + }, + "typography": { + "fontFamilies": [ "" ] + } + } +} +``` + +```json +{ + "settings": { + "color": { + "palette": [ "" ] + } + } +} +``` + +The result after the consolidation would be: + +```json +{ + "settings": { + "color": { + "palette": { + "default": [ "" ], + "theme": [ "" ], + "user": [ "" ] + }, + "gradients": { + "default": [ "" ] + } + }, + "typography": { + "fontFamilies": { + "theme": [ "" ] + } + } + } +} +``` + +#### From data to styles + +The last phase of generating the stylesheet is converting the consolidated data into CSS style rules. + +##### Styles to CSS rules + +The `styles` section can be thought of as a structured representation of CSS rules, each chunk representing a CSS rule: + +- A key/value in theme.json maps to a CSS declaration (`property: value`). +- The CSS selector for a given chunk is generated based on its semantics: + - The top-level section uses the `body` selector. + - The top-level elements use an ID selector matching the HTML element they represent (for example, `h1` or `a`). + - Blocks use the default class name they generate (`core/group` becomes `.wp-block-group`) unless they explicitly set a different one using their `block.json` (`core/paragraph` becomes `p`). See the "Current limits" section for more about this. + - Elements within a block use the concatenation of the block and element selector. + +For example, the following `theme.json` structure: + +```json +{ + "styles": { + "typography": { + "fontSize": "" + }, + "elements": { + "h1": { + "typography": { + "fontSize": "

" + } + } + }, + "blocks": { + "core/paragraph": { + "color": { + "text": "" + } + }, + "core/group": { + "color": { + "text": "" + }, + "elements": { + "h1": { + "color": { + "text": "

" + } + } + } + } + } + } +} +``` + +is converted to the following CSS: + +```css +body { + font-size: ; +} +h1 { + font-size:

; +} +p { + color: ; +} +.wp-block-group { + color: ; +} +.wp-block-group h1 { + color:

; +} +``` + +##### Settings to CSS rules + +From the `settings` section, all the values of any given presets will be converted to a CSS Custom Property that follows this naming structure: `--wp--preset---`. The selectors follow the same rules described in the styles section above. + +For example, the following theme.json + +```json +{ + "settings": { + "color": { + "palette": { + "default": [ + { "slug": "vivid-red", "value": "#cf2e2e", "name": "Vivid Red" } + ], + "theme": [ + { "slug": "foreground", "value": "#000", "name": "Foreground" } + ] + } + }, + "blocks": { + "core/site-title": { + "color": { + "palette": { + "theme": [ + { "slug": "foreground", "value": "#1a4548", "name": "Foreground" } + ] + } + } + } + } + } +} +``` + +Will be converted to the following CSS style rule: + +```CSS +body { + --wp--preset--color--vivid-red: #cf2e2e; + --wp--preset--color--foreground: #000; +} + +.wp-block-site-title { + --wp--preset--color--foreground: #1a4548; +} +``` + +In addition to the CSS Custom Properties, all presets but duotone generate CSS classes for each value. The example above will generate the following CSS classes as well: + +```CSS +/* vivid-red */ +.has-vivid-red-color { color: var(--wp--preset--color--vivid-red) !important; } +.has-vivid-red-background-color { background-color: var(--wp--preset--color--vivid-red) !important; } +.has-vivid-red-bordfer-color { border-color: var(--wp--preset--color--vivid-red) !important; } + +/* foreground */ +.has-foreground-color { color: var(--wp--preset--color--foreground) !important; } +.has-foreground-background-color { background-color: var(--wp--preset--color--foreground) !important; } +.has-foreground-border-color { border-color: var(--wp--preset--color--foreground) !important; } + +/* foreground within site title*/ +.wp-block-site-title .has-foreground-color { color: var(--wp--preset--color--foreground) !important; } +.wp-block-site-title .has-foreground-background-color { background-color: var(--wp--preset--color--foreground) !important; } +.wp-block-site-title .has-foreground-border-color { border-color: var(--wp--preset--color--foreground) !important; } +``` + +#### Current limitations of the Global Styles API + +1. **Setting a different CSS selector for blocks requires server-registration** + +By default, the selector assigned to a block is `.wp-block-`. However, blocks can change this should they need. They can provide a CSS selector via the `__experimentalSelector` property in its `block.json`. + +If blocks do this, they need to be registered in the server using the `block.json`, otherwise, the global styles code doesn't have access to that information and will use the default CSS selector for the block. + +2. **Can't target different HTML nodes for different styles** + +Every chunk of styles can only use a single selector. + +This is particularly relevant if the block is using `__experimentalSkipSerialization` to serialize the different style properties to different nodes other than the wrapper. See "Current limitations of blocks supports" for more. + +3. **Only a single property per block** + +Similarly to block supports, there can be only one instance of any style in use by the block. For example, the block can only have a single font size. See related "Current limitations of block supports". + +4. **Only blocks using block supports are shown in the Global Styles UI** + +The global styles UI in the site editor has a screen for per-block styles. The list of blocks is generated dynamically using the block supports from the `block.json` of blocks. If a block wants to be listed there, it needs to use the block supports mechanism. diff --git a/docs/explanations/glossary.md b/docs/explanations/glossary.md index 1e3eca1ff4517..bff8925e4619e 100644 --- a/docs/explanations/glossary.md +++ b/docs/explanations/glossary.md @@ -18,6 +18,8 @@ The CSS styles that are part of the block, either via its stylesheet or via the Compare to Global Styles. In contraposition to Global Styles, block styles are sometimes referred to as Local Styles. +Learn more about [Block Styles](/docs/explanations/architecture/styles.md#block-styles). + ## Block Supports An API for blocks to declare what features they support. By declaring support for a feature, the API would add additional attributes to the block and matching UI controls for most of the existing block supports. @@ -68,7 +70,7 @@ This refers to a collection of features that ultimately allows users to edit the The CSS styles generated by WordPress and enqueued as an embedded stylesheet in the front end of the site. The stylesheet ID is `global-styles-inline-css`. The contents of this stylesheet come from the default `theme.json` of WordPress, the theme's `theme.json`, and the styles provided by the user via the global styles sidebar in the site editor. -See theme.json reference docs and the how to guide. +See [theme.json reference docs](/docs/reference-guides/theme-json-reference.md), the [how to guide](/docs/how-to-guides/themes/theme-json.md), and an introduction to [styles in the block editor](/docs/explanations/architecture/styles.md). Compare to block styles. diff --git a/docs/manifest.json b/docs/manifest.json index 9ba8344f3ed30..0a6a9de90166c 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1919,6 +1919,12 @@ "markdown_source": "../docs/explanations/architecture/full-site-editing-templates.md", "parent": "architecture" }, + { + "title": "Styles", + "slug": "styles", + "markdown_source": "../docs/explanations/architecture/styles.md", + "parent": "architecture" + }, { "title": "Frequently Asked Questions", "slug": "faq", diff --git a/docs/toc.json b/docs/toc.json index 527ac165faa22..1e8e83bfa75c4 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -274,7 +274,8 @@ }, { "docs/explanations/architecture/full-site-editing-templates.md": [] - } + }, + { "docs/explanations/architecture/styles.md": [] } ] }, { "docs/explanations/faq.md": [] },