[wp-trac] [WordPress Trac] #64418: Valid CSS is causing failure in the Additional CSS panel
WordPress Trac
noreply at wordpress.org
Tue Dec 23 12:17:13 UTC 2025
#64418: Valid CSS is causing failure in the Additional CSS panel
--------------------------+-------------------------
Reporter: drw158 | Owner: jonsurrell
Type: defect (bug) | Status: assigned
Priority: normal | Milestone: 7.0
Component: Customize | Version: 4.7
Severity: normal | Resolution:
Keywords: has-patch | Focuses: css
--------------------------+-------------------------
Comment (by jonsurrell):
Replying to [comment:16 westonruter]:
> I believe we need a workaround similar to what was done in
`WP_Customize_Manager::save_changeset_post()` for storing Customizer
changesets (the `customize_changeset` CPT) where it wraps the call to
`wp_update_post()` as follows…
I think you're right. These default filters on post content are all
intended to run on HTML and are unsuitable for other content types like
CSS (even if it's CSS intended for a `<style>` element).
I have concerns because global styles stores JSON with a bunch of fields
and I'm not familiar with the entire structure and how it's used or may be
used in the future.
Below is an example of a `wp_global_styles` post type. This all appears to
be intended for use inside of CSS, but it's not a single CSS text. It's
parts of CSS that's going to be stitched together in some way. That makes
it very difficult to reason about what's actually safe in here until we
rely on things like the HTML API for constructing STYLE tags where we can
be confident that the CSS text is correctly prepared (escaped) for an HTML
STYLE tag.
{{{#!json
{
"styles": {
"css": "@property --animate {\n syntax: \"<custom-ident>\";\n
inherits: true;\n initial-value: false;\n}\n at property --base-animation-
duration {\n syntax: \"<time>\";\n inherits: true;\n initial-value:
300ms;\n}\n at keyframes marquee {\n 0% {\n transform: rotate(-10deg)
scale(0.9);\n }\n 100% {\n transform: rotate(12deg) scale(1.2);\n
}\n}\nmain {\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n --animate:
marquee;\n position: relative;\n\n &::after {\n color: red;\n
display: inline-block;\n animation: var(--animate) 600ms linear
infinite alternate;\n }\n }\n\n h1 {\n counter-increment:
heading-1;\n counter-reset: heading-2 heading-3 heading-4 heading-5
heading-6;\n &::after {\n content: \"<h1> \" counter(heading-1);\n
animation-duration: calc(var(--base-animation-duration) * 2);\n }\n
}\n h2 {\n counter-increment: heading-2;\n counter-reset: heading-3
heading-4 heading-5 heading-6;\n &::after {\n content: \"<h2> \"
counter(heading-1) \".\" counter(heading-2);\n animation-duration:
calc(var(--base-animation-duration) * 3);\n }\n }\n h3 {\n
counter-increment: heading-3;\n counter-reset: heading-4 heading-5
heading-6;\n &::after {\n content: \"<h3> \" counter(heading-1)
\".\" counter(heading-2) \".\"\n counter(heading-3);\n
animation-duration: calc(var(--base-animation-duration) * 5);\n }\n
}\n h4 {\n counter-increment: heading-4;\n counter-reset: heading-5
heading-6;\n &::after {\n content: \"<h4> \" counter(heading-1)
\".\" counter(heading-2) \".\"\n counter(heading-3) \".\"
counter(heading-4);\n animation-duration: calc(var(--base-animation-
duration) * 7);\n }\n }\n\n h5 {\n counter-increment: heading-5;\n
counter-reset: heading-6;\n &::after {\n content: \"<h5> \"
counter(heading-1) \".\" counter(heading-2) \".\"\n
counter(heading-3) \".\" counter(heading-4) \".\" counter(heading-5);\n
animation-duration: calc(var(--base-animation-duration) * 11);\n }\n
}\n\n h6 {\n counter-increment: heading-6;\n &::after {\n
content: \"<h6> \" counter(heading-1) \".\" counter(heading-2) \".\"\n
counter(heading-3) \".\" counter(heading-4) \".\" counter(heading-5)
\".\"\n counter(heading-6);\n animation-duration: calc(var
(--base-animation-duration) * 13);\n }\n }\n}",
"blocks": {
"core/paragraph": {
"css": "content: \"<script>alert(1);</script>\""
},
"core/site-title": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--beiruti)",
"fontWeight": "600",
"letterSpacing": "2.4px",
"textTransform": "uppercase"
}
}
},
"color": {
"background": "var(--wp--preset--color--accent-5)"
},
"elements": {
"h4": {
"typography": {
"fontSize": "var(--wp--preset--font-size--large)"
}
},
"heading": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--beiruti)",
"fontWeight": "500",
"letterSpacing": "-0.02em",
"lineHeight": "1.02"
}
}
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--literata)",
"fontSize": "var(--wp--preset--font-size--medium)",
"letterSpacing": "-0.01em",
"lineHeight": "1.6"
}
},
"settings": {
"color": {
"palette": {
"theme": [
{
"color": "#FFFFFF",
"name": "Base",
"slug": "base"
},
{
"color": "color-mix(in srgb, currentColor 20%, transparent)",
"name": "Accent 6",
"slug": "accent-6"
}
]
}
},
"typography": {
"fontFamilies": {
"theme": [
{
"name": "Beiruti",
"slug": "beiruti",
"fontFamily": "Beiruti, sans-serif",
"fontFace": [
{
"fontFamily": "Beiruti",
"fontStyle": "normal",
"fontWeight": "200 900",
"src": [
"file:./assets/fonts/beiruti/Beiruti-
VariableFont_wght.woff2"
]
}
]
}
]
},
"fontSizes": {
"theme": [
{
"fluid": {
"max": "2.8rem",
"min": "2rem"
},
"name": "Extra Extra Large",
"size": "2rem",
"slug": "xx-large"
}
]
}
}
},
"isGlobalStylesUserThemeJSON": true,
"version": 3
}
}}}
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64418#comment:18>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list