CINXE.COM

WebKit CSS Feature Status | WebKit

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta name="robots" content="noodp"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover"> <meta name="theme-color" content="hsl(203.6, 100%, 12%)"> <title> WebKit CSS Feature Status | WebKit</title> <meta name="application-name" content="WebKit"> <link rel="stylesheet" type="text/css" href="https://webkit.org/wp-content/themes/webkit/style.css?2022100501" media="all"> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?families=SF+Pro,v1" type="text/css"> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?families=SF+Mono,v2" type="text/css"> <meta name="supported-color-schemes" content="light dark"> <noscript> <img src="https://shynet.webkit.org/ingress/561b9e53-fb8c-4297-ae4d-bde05e8daa59/pixel.gif"> </noscript> <script defer src="https://shynet.webkit.org/ingress/561b9e53-fb8c-4297-ae4d-bde05e8daa59/script.js"></script> <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://webkit.org/feed/"> <link rel="alternate" type="text/xml" title="RSS .92" href="https://webkit.org/feed/rss/"> <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="https://webkit.org/feed/atom/"> <link rel="pingback" href="https://webkit.org/wp/xmlrpc.php"> <link rel="shortcut icon" sizes="32x32" type="image/x-icon" href="/favicon.ico"> <meta name='robots' content='max-image-preview:large' /> <link rel='stylesheet' id='wp-block-library-css' href='https://webkit.org/wp/wp-includes/css/dist/block-library/style.min.css?ver=6.7' type='text/css' media='all' /> <style id='classic-theme-styles-inline-css' type='text/css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <style id='global-styles-inline-css' type='text/css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} </style> <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://webkit.org/wp/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress 6.7" /> <link rel="canonical" href="https://webkit.org/css-status/" /> <link rel='shortlink' href='https://webkit.org/?p=7427' /> <link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2Fcss-status%2F" /> <link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2Fcss-status%2F&#038;format=xml" /> <!-- Schema.org markup --> <meta itemprop="name" content="WebKit CSS Feature Status"> <!-- Twitter Card data --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:image:src" content="https://webkit.org/wp-content/themes/webkit/images/twitter-card.png"> <meta name="twitter:site" content="@webkit"> <meta name="twitter:title" content="WebKit CSS Feature Status"> <!-- Open Graph data --> <meta property="og:title" content="WebKit CSS Feature Status"> <meta property="og:type" content="article"> <meta property="og:url" content="https://webkit.org/css-status/"> <meta property="og:site_name" content="WebKit"> <meta property="article:published_time" content="2017-02-28T13:31:58-08:00"> <meta property="article:modified_time" content="2018-12-20T10:18:43-08:00"> <meta property="fb:admins" content="1085088865"> </head> <body class="page-template page-template-css-status page-template-css-status-php page page-id-7427"> <!-- Copyright © 2020 Apple Inc. All rights reserved. --> <svg xmlns="http://www.w3.org/2000/svg"> <style> svg { display: block; width: 0; height: 0; } </style> <filter id="invertLightness" x="0" y="0" style="color-interpolation-filters: sRGB"> <feColorMatrix type="matrix" in="SourceGraphic" result="red" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1" /> <feColorMatrix type="matrix" in="SourceGraphic" result="green" values="0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1" /> <feColorMatrix type="matrix" in="SourceGraphic" result="blue" values="0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1" /> <feBlend in="red" in2="green" mode="lighten" result="maxyellow" /> <feBlend in="maxyellow" in2="blue" mode="lighten" result="max" /> <feBlend in="red" in2="green" mode="darken" result="minyellow" /> <feBlend in="minyellow" in2="blue" mode="darken" result="min" /> <feComponentTransfer result="adjustment" in="min"> <feFuncR type="linear" intercept="1" slope="-1" /> <feFuncG type="linear" intercept="1" slope="-1" /> <feFuncB type="linear" intercept="1" slope="-1" /> </feComponentTransfer> <feComposite operator="arithmetic" in="SourceGraphic" in2="adjustment" k1="0" k2="1" k3="1" k4="-1" result="channelAdjustment" /> <feComposite operator="arithmetic" in="channelAdjustment" in2="max" k1="0" k2="1" k3="-1" k4="1" result="finalColors" /> <feComposite operator="in" in="finalColors" in2="SourceAlpha" /> </filter> </svg> <header aria-label="WebKit.org Header" id="header"> <div class="page-width"> <a href="/"><div id="logo" class="site-logo">WebKit</div></a> <nav id="site-nav" aria-label="Site Menu"> <div class="menu-main-menu-container"><input type="checkbox" id="menu-main-menu-toggle" class="menu-toggle" /><label for="menu-main-menu-toggle" class="label-toggle main-menu" data-open="Main Menu" data-close="Close Menu"></label><ul id="menu-main-menu" class="menu" role="menubar"><li id="menu-item-6091" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-6091"><a href="https://webkit.org/downloads/" role="menuitem">Downloads</a></li> <li id="menu-item-4272" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-ancestor current-menu-parent current_page_parent current_page_ancestor menu-item-has-children menu-item-4272"><input type="checkbox" id="toggle-4272" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4272" aria-controls="sub-menu-for-4272" aria-expanded="true"><label for="toggle-4272" class="label-toggle">Feature Status</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4272"> <li id="menu-item-13052" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-7427 current_page_item menu-item-13052"><a href="https://webkit.org/css-status/" role="menuitem">CSS Features</a></li> <li id="menu-item-14388" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-14388"><a href="https://webkit.org/standards-positions/" role="menuitem">Standards Positions</a></li> </ul> </li> <li id="menu-item-9988" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-9988"><input type="checkbox" id="toggle-9988" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-9988" aria-controls="sub-menu-for-9988" aria-expanded="true"><label for="toggle-9988" class="label-toggle">Documentation</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-9988"> <li id="menu-item-9989" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-9989"><a href="/web-inspector" role="menuitem">Web Inspector</a></li> <li id="menu-item-10868" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10868"><a href="https://webkit.org/tracking-prevention/" role="menuitem">Tracking Prevention</a></li> </ul> </li> <li id="menu-item-4282" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-4282"><input type="checkbox" id="toggle-4282" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4282" aria-controls="sub-menu-for-4282" aria-expanded="true"><label for="toggle-4282" class="label-toggle">Policies</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4282"> <li id="menu-item-10037" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10037"><a href="https://webkit.org/project/" role="menuitem">Project Goals</a></li> <li id="menu-item-13077" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13077"><a href="https://webkit.org/bug-prioritization/" role="menuitem">Bug Prioritization</a></li> <li id="menu-item-13076" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13076"><a href="https://webkit.org/bug-report-guidelines/" role="menuitem">Bug Report Guidelines</a></li> <li id="menu-item-13075" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13075"><a href="https://webkit.org/code-style-guidelines/" role="menuitem">Code Style Guidelines</a></li> <li id="menu-item-13074" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13074"><a href="https://webkit.org/commit-and-review-policy/" role="menuitem">Commit and Review Policy</a></li> <li id="menu-item-13073" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13073"><a href="https://webkit.org/feature-policy/" role="menuitem">Feature Policy</a></li> <li id="menu-item-13072" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13072"><a href="https://webkit.org/security-policy/" role="menuitem">Security Policy</a></li> <li id="menu-item-13071" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13071"><a href="https://webkit.org/tracking-prevention-policy/" role="menuitem">Tracking Prevention Policy</a></li> </ul> </li> <li id="menu-item-4274" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4274"><input type="checkbox" id="toggle-4274" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4274" aria-controls="sub-menu-for-4274" aria-expanded="true"><label for="toggle-4274" class="label-toggle">Contribute</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4274"> <li id="menu-item-4277" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4277"><a href="https://webkit.org/getting-started/" role="menuitem">Getting Started</a></li> <li id="menu-item-4284" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4284"><a href="https://webkit.org/contributing-code/" role="menuitem">Contributing Code</a></li> <li id="menu-item-4281" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4281"><a href="https://webkit.org/testing-contributions/" role="menuitem">Testing Contributions</a></li> <li id="menu-item-4273" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4273"><a href="https://webkit.org/reporting-bugs/" role="menuitem">How to Report Bugs</a></li> <li id="menu-item-4278" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4278"><a href="https://github.com/WebKit/WebKit" role="menuitem">GitHub Repository</a></li> </ul> </li> <li id="menu-item-4270" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-4270"><input type="checkbox" id="toggle-4270" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4270" aria-controls="sub-menu-for-4270" aria-expanded="true"><label for="toggle-4270" class="label-toggle">Blog</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4270"> <li id="menu-item-13057" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13057"><a href="https://webkit.org/blog/category/news/" role="menuitem">News Posts</a></li> <li id="menu-item-13058" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13058"><a href="https://webkit.org/blog/category/css/" role="menuitem">CSS Posts</a></li> <li id="menu-item-13063" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13063"><a href="https://webkit.org/blog/category/contributing/" role="menuitem">Contributing Posts</a></li> <li id="menu-item-13062" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13062"><a href="https://webkit.org/blog/category/privacy/" role="menuitem">Privacy Posts</a></li> <li id="menu-item-13060" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13060"><a href="https://webkit.org/blog/category/performance/" role="menuitem">Performance Posts</a></li> <li id="menu-item-13061" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13061"><a href="https://webkit.org/blog/category/javascript/" role="menuitem">JavaScript Posts</a></li> <li id="menu-item-13056" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13056"><a href="https://webkit.org/blog/category/standards/" role="menuitem">Standards Posts</a></li> <li id="menu-item-13059" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13059"><a href="https://webkit.org/blog/category/web-inspector/" role="menuitem">Web Inspector Posts</a></li> <li id="menu-item-13055" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13055"><a href="https://webkit.org/blog/category/safari-technology-preview/" role="menuitem">Safari Technology Preview Posts</a></li> </ul> </li> <li><form action="/" method="get"><input type="search" name="s" class="search-input" value=""></form></li></ul></div></nav> </div> </header> <main id="content"> <div class="page-width"><script> function xhrPromise(url) { return new Promise(function(resolve, reject) { var xhrRequest = new XMLHttpRequest(); xhrRequest.open('GET', url, true); xhrRequest.responseType = "json"; xhrRequest.onload = function() { if (xhrRequest.status == 200 || xhrRequest.status == 0) { if (xhrRequest.response) { resolve(xhrRequest.response); } else { reject({ request: xhrRequest, url:url}); } } else { reject({ request: xhrRequest, url:url}); } }; xhrRequest.onerror = function() { reject({ request: xhrRequest, url:url}); }; xhrRequest.send(); }); } var origin = new URL("https://raw.githubusercontent.com/"); var loadCSSProperties = xhrPromise(new URL("/WebKit/WebKit/main/Source/WebCore/css/CSSProperties.json", origin)); </script> <style> :root { --feature-rule-color: hsl(0, 0%, 89.4%); --status-color: hsl(0, 0%, 60%); --supported-color: hsl(100, 100%, 30%); --non-standard-color: hsl(275.4, 77.7%, 35.1%); --in-development-color: hsl(24.5, 91.3%, 50.6%); --experimental-color: hsl(211.3, 100%, 50%); --obsolete-color: hsl(50, 100%, 25.1%); } @media(prefers-color-scheme:dark) { :root { --feature-rule-color: hsl(0, 0%, 20%); --status-color: hsl(0, 0%, 51%); --supported-color: hsl(79.5, 45.3%, 52%); --non-standard-color: hsl(276.7, 36.3%, 51.4%); --in-development-color: hsl(24.5, 91.3%, 50.6%); --experimental-color: hsl(211.3, 100%, 50%); --obsolete-color: hsl(31.9, 20.5%, 33.1%); } } .feature-status-page { animation: none !important; /* This animation can trigger a hit-testing bug, so remove it for now */ } .page { display: -webkit-flex; display: flex; flex-direction: column; -webkit-justify-content: space-between; justify-content: space-between; box-sizing: border-box; width: 100%; } .page h1 { font-size: 4.2rem; font-weight: 500; line-height: 6rem; margin: 3rem auto; width: 100%; text-align: center; } .page h1 a { color: inherit; } .page h2 { font-weight: 200; font-size: 3rem; } .page h3 { font-weight: 400; font-size: 2.2rem; } .css-feature-page { padding-bottom: 3rem; } .css-feature-page p { max-width: 920px; margin: 0 auto 3rem; } /* Feature Filters */ .feature-filters { background-color: hsl(0, 0%, 0%); background-color: var(--figure-mattewhite-background-color); width: 100vw; left: 50%; position: relative; transform: translate(-50vw, 0); box-sizing: border-box; margin-bottom: 3rem; border: 1px solid hsl(0, 0%, 90.6%); border-color: var(--article-border-color); border-left: none; border-right: none; } .feature-filters .search-input { background-repeat: no-repeat; background-position-x: 0.5rem; background-position-y: 1rem; background-size: 2rem; padding: 1rem; padding-left: 3rem; padding-right: 8.5rem; font-size: 2rem; width: 100%; margin-top: 0rem; margin-bottom: 0rem; box-sizing: border-box; border-color: transparent; } .feature-filters li { display: inline-block; white-space: no-wrap; } .property-status label, .feature-filters label { display: table-cell; padding: 0.5rem 1rem; border-style: solid; border-width: 1px; border-radius: 3px; cursor: pointer; float: right; line-height: 1; font-size: 1.6rem; } #status-filters { display: none; text-align: center; margin-top: 1rem; margin-bottom: 0; } .property-filters { max-width: 920px; margin: 0 auto 0; position: relative; top: 0; } .property-filters.opened { margin-top: 1.5rem; } .property-filters.opened #status-filters { display: block; } #status-filters label { margin-left: 1rem; margin-bottom: 1rem; float: none; display: inline-block; position: relative; } .feature-filters label { float: none; display: inline-block; } .status-filters { list-style: none; display: inline-block; text-align: center; } .filter-toggle:checked + .filter-status { color: hsl(240, 1.3%, 84.5%); color: var(--text-color); } .filter-status, .feature-status { color: hsl(0, 0%, 60%); color: var(--status-color); border-color: hsl(0, 0%, 60%); border-color: var(--status-color); } .feature-status a { color: inherit; } .status-filter, .status-marker { border-color: hsl(0, 0%, 60%); border-color: var(--status-color) } .filter-toggle:checked + .filter-status { background-color: hsl(0, 0%, 60%); background-color: var(--status-color); } .property-description.status-marker { border-left-width: 3px; border-left-style: solid; padding: 0.5rem 0 0.5rem 1rem; } .property-count { max-width: 920px; margin: 0 auto 3rem; text-align: right; color: hsl(240, 2.3%, 56.7%); color: var(--text-color-coolgray); } .property-header > h3:first-of-type { -webkit-flex-grow: 1; flex-grow: 1; margin: 0; } .property-header:after { position: relative; width: 2rem; height: 2rem; right: 0; top: 0.5rem; margin-left: 1rem; transition: transform 0.3s ease-out; } .properties { padding: 0; max-width: 920px; margin: 0 auto 3rem; border-bottom: 1px solid hsl(0, 0%, 89.4%); border-color: var(--feature-rule-color); } .properties .property { position: relative; display: block; max-height: intrinsic; min-height: 3rem; overflow-y: hidden; cursor: pointer; background-color: transparent; border-color: transparent; border-width: 1px; border-style: solid; border-top-color: hsl(0, 0%, 89.4%); border-top-color: var(--feature-rule-color); padding: 0.5rem; line-height: 1.618; transition: background-color 0.3s ease-in; } .property.opened { background-color: hsl(0, 0%, 100%); background-color: var(--figure-mattewhite-background-color); border-left-color: hsl(0, 0%, 89.4%); border-left-color: var(--feature-rule-color); border-right-color: hsl(0, 0%, 89.4%); border-right-color: var(--feature-rule-color); max-height: 120rem; } .property.opened .property-header:after { -webkit-transform: rotateX(-180deg); -moz-transform: rotateX(-180deg); transform: rotateX(-180deg); perspective: 600; } .property-description .toggleable { display: none; } .property.opened .property-description .toggleable { display: block; margin-top: 1rem; } .comment { font-size: smaller; } .more-info { margin-top: 0.5em; font-size: smaller; } .sub-features { font-size: 1.5rem; color: #555; } .sub-features ul { list-style: none; display: inline-block; padding: 0; margin: 0; } .sub-features li { display: inline; } .sub-features li:after { content: ", "; } .sub-features li:last-child:after { content: ""; } ul.values { margin-left: 3em; margin-bottom: 0.5em; cursor: default; } .values li.hidden { color: #444; } .property-header { position: relative; display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; } .property-header .toggle { display: inline-block; background: url('images/menu-down.svg') no-repeat 50%; background-size: 2rem; border: none; width: 2rem; height: 2rem; position: absolute; right: 0; top: 0.5rem; transition: transform 0.3s ease-out; } .property.opened .property-header .toggle { transform: rotateX(-180deg); } .property-header h3 .spec-label , .property-header h3 .spec-label a { text-decoration: none; font-weight: 200; color: hsl(0, 0%, 33.3%); color: var(--text-color-medium); } .spec-label::before { content: ' — '; } .property-description .toggleable { color: hsl(0, 0%, 20%); color: var(--text-color); } .property-header h3, .property-header a[name] { color: hsl(0, 0%, 26.7%); color: var(--text-color-heading); } .property-alias { font-size: smaller; } .property-header p { margin-top: 0.5rem; margin-bottom: 0.5rem; } .property-alias, .value-alias, .value-status { color: hsl(240, 2.3%, 56.7%); color: var(--text-color-coolgray); } .property.is-hidden { display: none; } ul.property-details { margin: 0; } .property-statusItem { margin-right: 0.5em; } .property-status, .property-status a { color: #999; } .property .status-marker { border-left-width: 3px; border-left-style: solid; padding: 0.5rem 0 0.5rem 1rem; } .status-marker { border-color: hsl(0, 0%, 60%); border-color: var(--status-color) } .supported { color: hsl(100, 100%, 30%); color: var(--supported-color); border-color: hsl(100, 100%, 30%); border-color: var(--supported-color); } .in-development { color: hsl(24.5, 91.3%, 50.6%); color: var(--in-development-color); border-color: hsl(24.5, 91.3%, 50.6%); border-color: var(--in-development-color); } .experimental { color: hsl(211.3, 100%, 50%); color: var(--experimental-color); border-color: hsl(211.3, 100%, 50%); border-color: var(--experimental-color); } .non-standard { color: hsl(275.4, 77.7%, 35.1%); color: var(--non-standard-color); border-color: hsl(275.4, 77.7%, 35.1%); border-color: var(--non-standard-color); } .obsolete { color: hsl(50, 100%, 25.1%); color: var(--obsolete-color); border-color: hsl(50, 100%, 25.1%); border-color: var(--obsolete-color); } .by-specification { background-color: hsl(0, 0%, 96.9%); background-color: var(--content-background-color); border-color: hsl(0, 0%, 83.9%); border-color: var(--input-border-color); } .property-filters.opened .search-input { border-color: hsl(0, 0%, 83.9%); border-color: var(--input-border-color); } .feature-filters .filters-toggle-button { background-repeat: no-repeat; background-size: 2rem; background-position: right; background-filter: lightness(2); position: absolute; padding-right: 2.5rem; right: 1rem; top: 1rem; border: none; color: hsl(240, 2.3%, 56.7%); } .feature-filters .filters-toggle-button:hover { filter: brightness(0); } #filters-toggle { display: none; } .property-filters ul { margin-top: 0.5rem; } .property-filters ul li { margin-bottom: 0.5rem; } .property-filters label > input { position: relative; top: -1px; } .prefixes { display: none; } #specifications { display: inline-block; font-size: 1.6rem; color: hsl(0, 0%, 20%); color: var(--text-color); margin-left: 1rem; } .filter-by-specifications-toggle { position: absolute; display: none; left: 1000rem; top: 0; width: 100%; height: 100%; } #specifications:disabled + .filter-by-specifications-toggle { display: block; top: 0; left: 0; } h3 a[name], .admin-bar h3 a[name] { top: initial; width: auto; display: inline-block; visibility: visible; /* Override visibility:hidden from themes/webkit/style.css */ } .pagination:after { display: none; } .pagination, .pagination + h1 { margin-top: 0; } @media only screen and (max-width: 1180px) { .feature-filters .filters-toggle-button { right: 3rem; } } @media only screen and (max-width: 508px) { #property-filters, #property-list { width: 100%; } #property-filters { padding-left: 2rem; padding-right: 2rem; } .property-header h3 { font-size: 2rem; padding-right: 0.5rem; } .property-status { font-size: 1.6rem; margin-top: 0.4rem; float: left; } .property-header:after { width: 1rem; height: 1rem; background-size: 1rem; top: 1rem; } .property h3 { font-size: 2rem; padding-top: 4rem; } .property-header .property-status { font-size: 1.6rem; position: absolute; text-align: left; } .property .moreinfo { flex-wrap: wrap; } .property .moreinfo .contact { text-align: left; } .status-filters { flex-basis: 100%; } .status-filters label { margin-left: 0; margin-right: 1rem; } } @media(prefers-color-scheme:dark) { .property-header:after { filter: invert(1); } .search-input:hover, .search-input:focus, .feature-filters .filters-toggle-button:hover { filter: brightness(2); } } </style> <div class="page css-feature-page" id="post-7427"> <div class="connected pagination"> </div> <h1><a href="https://webkit.org/css-status/" rel="bookmark" title="Permanent Link: WebKit CSS Feature Status">WebKit CSS Feature Status</a></h1> <section class="feature-filters"> <form id="property-filters" class="property-filters page-width"> <input type="text" id="search" class="search-input" placeholder="Search CSS Features&hellip;" title="Filter the property list." required><label class="filters-toggle-button">Filters</label> <ul id="status-filters"> </ul> <div class="prefixes"> <h2>Filter by Prefix</h2> <ul id="prefix-filters"> </ul> </div> </form> </section> <section class="primary"> <div id="property-list"> <div class="property-count"> <p><span id="property-count"></span> <span id="property-pluralize">properties</span></p> </div> </div> <template id="success-template"> <ul class="properties" id="properties-container"></ul> <p>Cannot find something? Standards positions can be found on <a href="https://github.com/WebKit/standards-positions">this Github repository</a>. For questions, feel free to contact the <a href="https://lists.webkit.org/mailman/listinfo/webkit-help">webkit-help</a> mailing list.</p> <p>You can also <a href="/contributing-code/">contribute to features</a> directly, the entire project is Open Source. To report bugs on existing features or check existing bug reports, see <a href="https://bugs.webkit.org">https://bugs.webkit.org</a>.</p> </template> <template id="error-template"> <p>Error: unable to load the features list (<span id="error-message"></span>).</p> <p>If this is not resolved soon, please contact <a href="https://twitter.com/webkit">@webkit</a> on Twitter or the <a href="https://lists.webkit.org/mailman/listinfo/webkit-help">webkit-help</a> mailing list.</p> </template> </section> </div> <script> "use strict"; function initializeStatusPage() { const statusOrder = [ 'supported', 'in-development', 'experimental', 'non-standard', 'obsolete', ]; const readableStatus = { 'supported': 'Supported', 'in-development': 'In Development', 'experimental': 'Experimental', 'non-standard': 'Non-standard', 'obsolete': 'Obsolete', }; function sortAlphabetically(array) { function replaceDashPrefix(name) { if (name[0] == '-') return 'Z' + name.slice(1); return name; } array.sort(function(a, b) { // Sort the prefixed properties to the end. var aName = replaceDashPrefix(a.name.toLowerCase()); var bName = replaceDashPrefix(b.name.toLowerCase()); var nameCompareResult = aName.localeCompare(bName); if (nameCompareResult) return nameCompareResult; // Status sort var aStatus = a.status != undefined ? a.status.status.toLowerCase() : ''; var bStatus = b.status != undefined ? b.status.status.toLowerCase() : ''; return aStatus.localeCompare(bStatus); }); } function propertyNameAliases(propertyObject) { if ('codegen-properties' in propertyObject && 'aliases' in propertyObject['codegen-properties']) return propertyObject['codegen-properties'].aliases; return []; } function propertyLonghands(propertyObject) { if ('codegen-properties' in propertyObject && 'longhands' in propertyObject['codegen-properties']) return propertyObject['codegen-properties'].longhands; return []; } const prefixRegexp = /^(-webkit-|-epub-|-apple-)(.+)$/; function createPropertyView(categoryObject, propertyObject) { function createLinkWithHeading(elementName, heading, linkText, linkUrl) { var container = document.createElement(elementName); if (heading) { container.textContent = heading + ": "; } var link = document.createElement("a"); link.textContent = linkText; link.href = linkUrl; container.appendChild(link); return container; } function appendValueWithLink(container, value, link) { if (link) { var anchor = document.createElement('a'); anchor.href = link; anchor.textContent = value; container.appendChild(anchor); return; } container.textContent = value; } function makeTwitterLink(twitterHandle) { if (twitterHandle[0] == "@") twitterHandle = twitterHandle.substring(1); return "https://twitter.com/" + twitterHandle; } var hasSpecificationObject = "specification" in propertyObject; var specificationObject = propertyObject.specification; var container = document.createElement('li'); container.className = "property"; var slug = propertyObject.name.toLowerCase().replace(/ /g, '-'); container.setAttribute("id", "property-" + slug); var descriptionContainer = document.createElement('div'); descriptionContainer.className = "property-description status-marker"; var featureHeaderContainer = document.createElement('div'); featureHeaderContainer.className = "property-header"; descriptionContainer.appendChild(featureHeaderContainer); var titleElement = document.createElement("h3"); var anchorLinkElement = document.createElement("a"); anchorLinkElement.href = "#" + container.getAttribute("id"); anchorLinkElement.name = container.getAttribute("id"); anchorLinkElement.textContent = propertyObject.name; titleElement.appendChild(anchorLinkElement); if (categoryObject) { if (specificationObject && ("url" in specificationObject || "obsolete-url" in specificationObject)) { var url = ("url" in specificationObject) ? specificationObject.url : specificationObject['obsolete-url']; var specSpan = createLinkWithHeading("span", null, categoryObject.shortname, specificationObject.url); specSpan.className = 'spec-label'; titleElement.appendChild(specSpan); } else { var labelSpan = document.createElement("span"); labelSpan.className = 'spec-label'; labelSpan.textContent = categoryObject.shortname; titleElement.appendChild(labelSpan); } } featureHeaderContainer.appendChild(titleElement); var toggledContentContainer = document.createElement('div'); toggledContentContainer.className = "toggleable"; descriptionContainer.appendChild(toggledContentContainer); var aliases = propertyNameAliases(propertyObject); if (aliases.length) { var propertyAliasDiv = document.createElement('div'); propertyAliasDiv.className = 'property-alias'; propertyAliasDiv.textContent = 'Also supported as: ' + aliases.join(', '); toggledContentContainer.appendChild(propertyAliasDiv); } var longhands = propertyLonghands(propertyObject); if (longhands.length) { var longhandsDiv = document.createElement('div'); longhandsDiv.className = 'longhands'; longhandsDiv.textContent = 'Shorthand for '; for (var i in longhands) { if (i > 0) longhandsDiv.appendChild(document.createTextNode(', ')); var longhand = longhands[i]; var longhandLink = document.createElement("a"); longhandLink.href = "#property-" + longhand; longhandLink.textContent = longhand; longhandsDiv.appendChild(longhandLink); } toggledContentContainer.appendChild(longhandsDiv); } function collapsePrefixedValues(values) { var remainingValues = []; var prefixMap = {}; for (var valueObj of values) { var valueName = valueObj.value; var result = prefixRegexp.exec(valueName); if (result) { var unprefixed = result[2]; var unprefixedValue = findValueByName(values, unprefixed); if (unprefixedValue) { (prefixMap[unprefixedValue.value] = prefixMap[unprefixedValue.value] || []).push(valueName); continue; } } remainingValues.push(valueObj); } for (var prefixed in prefixMap) { var unprefixedValue = findValueByName(remainingValues, prefixed); unprefixedValue.aliases = prefixMap[prefixed]; } return remainingValues; } if (propertyObject.values.length) { var valuesHeader = document.createElement("h4"); valuesHeader.textContent = 'Supported Values:'; toggledContentContainer.appendChild(valuesHeader); var valuesList = document.createElement("ul"); valuesList.className = 'values'; var values = collapsePrefixedValues(propertyObject.values); for (var valueObj of values) { var li = document.createElement("li"); valueObj.el = li; var link = undefined; var valueAliases = undefined; var status = undefined; if ('aliases' in valueObj) valueAliases = valueObj.aliases; if ('status' in valueObj) status = valueObj.status; if ('url' in valueObj) link = valueObj['url']; appendValueWithLink(li, valueObj.value, link); if (valueAliases) { var span = document.createElement('span'); span.textContent = ' (' + valueAliases.join(', ') + ')'; span.className = 'value-alias'; li.appendChild(span); } if (status) { var span = document.createElement('span'); span.textContent = ' (' + status + ')'; span.className = 'value-status'; li.appendChild(span); } valuesList.appendChild(li); } toggledContentContainer.appendChild(valuesList); } var statusContainer = document.createElement("div"); descriptionContainer.classList.add(propertyObject.status.status); statusContainer.className = "property-status " + propertyObject.status.status; var statusLabel = document.createElement("label"); if ("webkit-url" in propertyObject) { var statusLink = document.createElement("a"); statusLink.href = propertyObject["webkit-url"]; statusLink.textContent = readableStatus[propertyObject.status.status]; statusLabel.appendChild(statusLink); } else { statusLabel.textContent = readableStatus[propertyObject.status.status]; } statusContainer.appendChild(statusLabel); featureHeaderContainer.appendChild(statusContainer); var toggle = document.createElement('button'); toggle.className = 'toggle'; container.addEventListener('click', function (e) { container.classList.toggle('opened'); }); featureHeaderContainer.appendChild(toggle); if (specificationObject && "description" in specificationObject) { var testDescription = document.createElement('p'); testDescription.className = "property-desc"; testDescription.innerHTML = specificationObject.description; toggledContentContainer.appendChild(testDescription); } if (specificationObject && "comment" in specificationObject) { if ("description" in specificationObject) { var hr = document.createElement("hr"); hr.className = 'comment'; toggledContentContainer.appendChild(hr); } var comment = document.createElement('p'); comment.className = 'comment'; comment.innerHTML = specificationObject.comment; toggledContentContainer.appendChild(comment); } if (propertyObject.status && "comment" in propertyObject.status) { var comment = document.createElement('p'); comment.className = 'comment'; comment.innerHTML = propertyObject.status.comment; toggledContentContainer.appendChild(comment); } container.appendChild(descriptionContainer); function getMostSpecificProperty(categoryObject, specificationObject, attributeName) { // The url in the specification object is more specific, so use it if present. if (specificationObject && attributeName in specificationObject) return specificationObject[attributeName]; return categoryObject[attributeName]; } var hasReferenceLink = categoryObject && "url" in categoryObject; var hasDocumentationLink = (specificationObject && "documentation-url" in specificationObject) || (categoryObject && "documentation-url" in categoryObject); var hasContactObject = specificationObject && "contact" in specificationObject; if (hasDocumentationLink || hasReferenceLink || hasContactObject) { var moreInfoList = document.createElement("ul"); moreInfoList.className = 'more-info'; if (hasDocumentationLink) { // The url in the specification object is more specific, so use it if present. var url = getMostSpecificProperty(categoryObject, specificationObject, 'documentation-url'); moreInfoList.appendChild(createLinkWithHeading("li", "Documentation", url, url)); } if (hasReferenceLink) { var url = getMostSpecificProperty(categoryObject, specificationObject, 'url'); moreInfoList.appendChild(createLinkWithHeading("li", "Reference", url, url)); if ('obsolete-url' in specificationObject){ var url = specificationObject['obsolete-url']; moreInfoList.appendChild(createLinkWithHeading("li", "Reference", url, url)); } } if (hasContactObject) { var li = document.createElement("li"); li.textContent = "Contact: "; var contactObject = specificationObject.contact; if (contactObject.twitter) { li.appendChild(createLinkWithHeading("span", null, contactObject.twitter, makeTwitterLink(contactObject.twitter))); } if (contactObject.email) { if (contactObject.twitter) { li.appendChild(document.createTextNode(" - ")); } var emailText = contactObject.email; if (contactObject.name) { emailText = contactObject.name; } li.appendChild(createLinkWithHeading("span", null, emailText, "mailto:" + contactObject.email)); } moreInfoList.appendChild(li); } toggledContentContainer.appendChild(moreInfoList); } return container; } function canonicalizeIdentifier(identifier) { return identifier.toLocaleLowerCase().replace(/ /g, '-'); } function renderSpecifications(categories, properties, selectedSpecifications) { var specificationsList = document.getElementById('specifications'); specificationsList.addEventListener('change', function() { updateSearch(properties); }); var selectedIndex = -1; var allCategories = Object.keys(categories).sort(); for (var i = 0; i < allCategories.length; ++i) { var categoryKey = allCategories[i]; var category = categories[categoryKey]; categoryKey = canonicalizeIdentifier(categoryKey); var option = document.createElement("option"); option.setAttribute('value', categoryKey); if (selectedSpecifications.indexOf(categoryKey) != -1) selectedIndex = i; option.appendChild(document.createTextNode(" " + category['shortname'])); specificationsList.appendChild(option); } if (selectedIndex != -1) specificationsList.selectedIndex = selectedIndex; } function getPropertyCategory(propertyObject) { if ('specification' in propertyObject && 'category' in propertyObject.specification) return propertyObject.specification.category; return undefined; } function renderProperties(categories, propertyObjects) { var propertiesContainer = document.getElementById('properties-container'); for (var propertyObject of propertyObjects) { var category = getPropertyCategory(propertyObject); propertiesContainer.appendChild(createPropertyView(categories[category], propertyObject)); } } function convertToTitleCase(string) { return string.replace(/\w\S*/g, function(txt){ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); } function initSearch(properties, categories) { var filtersForm = document.getElementById('property-filters'); var filtersToggleButton = document.getElementsByClassName('filters-toggle-button')[0]; var statusContainer = document.getElementById('status-filters'); var inputField = document.getElementById('search'); var featuresEls = document.querySelectorAll('.properties > li'); var statusFilters = {}; properties.forEach(function(property, i) { property.el = featuresEls[i]; property.visible = true; // FIXME: need status per value as well. if (property.status != undefined) { let propertyStatusKey = property.status.status.toLocaleLowerCase(); if (!statusFilters[propertyStatusKey]) statusFilters[propertyStatusKey] = property.status.status; if (statusOrder.indexOf(propertyStatusKey) == -1) window.console.log('Status ' + propertyStatusKey + ' is not one of the predefined status keys ', statusOrder); } }); var selectedStatuses = statusesFromURL(); var selectedSpecs = specificationsFromURL(); for (var key of statusOrder) { var status = statusFilters[key]; var canonicalStatus = canonicalizeIdentifier(status); var entry = document.createElement("li"); var label = document.createElement("label"); var input = document.createElement("input"); input.setAttribute('type','checkbox'); input.setAttribute('value', canonicalStatus); if (selectedStatuses.indexOf(canonicalStatus) != -1) { filtersForm.classList.add('opened'); input.checked = true; } input.className = 'status-checkbox'; input.addEventListener('change', function() { updateSearch(properties); }); label.appendChild(input); label.className = "status-filter " + canonicalStatus; label.appendChild(document.createTextNode(" " + readableStatus[status])); entry.appendChild(label); statusContainer.appendChild(entry); } // Append the special "By Specification" checkbox { var entry = document.createElement("li"); var label = document.createElement("label"); var input = document.createElement("input"); input.id = 'by-spec-checkbox'; input.setAttribute('type','checkbox'); if (selectedSpecs.length > 0) input.checked = true; input.addEventListener('change', function() { updateSearch(properties); }); label.appendChild(input); label.className = "status-filter by-specification"; label.appendChild(document.createTextNode(" By Specification:")); var specsList = document.createElement('select'); specsList.className = 'specifications'; specsList.id = 'specifications'; specsList.addEventListener('mousedown', function() { input.setAttribute('checked','checked'); input.checked = true; console.log(input); input.checked = true; }); var specsListToggle = document.createElement('div'); specsListToggle.className = 'filter-by-specifications-toggle'; label.appendChild(specsList); label.appendChild(specsListToggle); entry.appendChild(label); statusContainer.appendChild(entry); } filtersToggleButton.addEventListener('mousedown', function (e) { filtersForm.classList.toggle('opened'); }); var searchTerm = searchTermFromURL(); if (searchTerm.length) { inputField.value = searchTerm; inputField.placeholder = ''; } inputField.addEventListener('input', function() { updateSearch(properties); }); var inputs = [].slice.call(filtersForm.getElementsByTagName('input')); inputs.forEach(function (input,i) { input.addEventListener('click', function (e) { e.stopPropagation(); }); }); renderSpecifications(categories, properties, selectedSpecs); } function getValuesOfCheckedItems(items) { var checkedValues = []; items.forEach(function(item,i) { if (item.checked) checkedValues.push(item.value); }); return checkedValues; } function getValuesOfSelectedItems(select) { var selectedValues = []; if (select.selectedIndex != -1) selectedValues.push(select.options[select.selectedIndex].value); return selectedValues; } function selectedSpecifications() { var specificationsList = document.getElementById('specifications'); if (!document.getElementById('by-spec-checkbox').checked) { specificationsList.disabled = true; return []; } specificationsList.disabled = false; return getValuesOfSelectedItems(specificationsList); } function updateSearch(properties) { var inputField = document.getElementById('search'); var statusContainer = document.getElementById('status-filters'); var searchTerm = inputField.value.trim().toLowerCase(); var activeStatusFilters = getValuesOfCheckedItems([].slice.call(statusContainer.querySelectorAll('.status-checkbox'))); var prefixContainer = document.getElementById('prefix-filters'); var activePrefixFilters = getValuesOfCheckedItems([].slice.call(prefixContainer.getElementsByTagName('input'))); var numVisible = searchProperties(properties, searchTerm, selectedSpecifications(), activeStatusFilters, activePrefixFilters); document.getElementById('property-pluralize').textContent = numVisible == 1 ? 'property' : 'properties'; document.getElementById('property-count').textContent = numVisible; updateSpecsState(); updateURL(searchTerm, selectedSpecifications(), activeStatusFilters, activePrefixFilters); } function updateSpecsState() { var specsEnabled = document.getElementById('by-spec-checkbox').checked; var specificationsList = document.getElementById('specifications'); var radiobuttons = [].slice.call(specificationsList.getElementsByTagName('input')); radiobuttons.forEach(function(radiobutton,i) { radiobutton.disabled = !specsEnabled; }); } function updateURL(searchTerm, selectedSpecifications, activeStatusFilters, activePrefixFilters) { var searchString = ''; function appendDelimiter() { searchString += searchString.length ? '&' : '?'; } if (searchTerm.length > 0) { appendDelimiter(); searchString += 'search=' + encodeURIComponent(searchTerm); } if (activeStatusFilters.length) { appendDelimiter(); searchString += 'status=' + activeStatusFilters.join(','); } if (selectedSpecifications.length) { appendDelimiter(); searchString += 'specs=' + selectedSpecifications.join(','); } if (activePrefixFilters.length) { appendDelimiter(); searchString += 'prefix=' + activePrefixFilters.join(','); } var current = window.location.href; window.location.href = current.replace(/#(.*)$/, '') + '#' + searchString; } function searchTermFromURL() { var search = window.location.search; var searchRegExp = /\#.*search=([^&]+)/; var result; if (result = window.location.href.match(searchRegExp)) return decodeURIComponent(result[1]); return ''; } function statusesFromURL() { var search = window.location.search; var statusRegExp = /\#.*status=([^&]+)/; var result; if (result = window.location.href.match(statusRegExp)) return result[1].split(','); return []; } function specificationsFromURL() { var search = window.location.search; var specsRegExp = /\#.*specs=([^&]+)/; var result; if (result = window.location.href.match(specsRegExp)) return result[1].split(','); return []; } function valueOrAliasIsPrefixed(valueObj) { if (prefixRegexp.exec(valueObj.value)) return true; if ('alias' in valueObj) { for (var alias of valueObj.aliases) { if (prefixRegexp.exec(alias)) return true; } } return false; } function filterValues(propertyObject, searchTerm, categories, statusFilters) { for (var valueObj of propertyObject.values) { if (!valueObj.el) continue; var visible = false; visible = valueObj.value.toLowerCase().indexOf(searchTerm) !== -1; if (!visible) { for (var currValueObj of propertyObject.values) { if (valueOrAliasIsPrefixed(currValueObj)) { visible = true; break; } } } if (!visible) { for (var currValueObj of propertyObject.values) { if (prefixRegexp.exec(currValueObj.value)) { visible = true; break; } } } if (visible) valueObj.el.classList.remove('hidden'); else valueObj.el.classList.add('hidden'); } } function searchProperties(properties, searchTerm, categories, statusFilters, prefixFilters) { var visibleCount = 0; properties.forEach(function(propertyObject) { var matchesStatusSearch = isStatusFiltered(propertyObject, statusFilters); var matchesPrefixSearch = isPrefixFiltered(propertyObject, prefixFilters); var visible = propertyIsSearchMatch(propertyObject, searchTerm) && isCategoryMatch(propertyObject, categories) && matchesStatusSearch && matchesPrefixSearch; if (visible && !propertyObject.visible) propertyObject.el.className = 'property'; else if (!visible && propertyObject.visible) propertyObject.el.className = 'property is-hidden'; if (visible) { filterValues(propertyObject, searchTerm); ++visibleCount; } propertyObject.visible = visible; }); return visibleCount; } function propertyIsSearchMatch(propertyObject, searchTerm) { if (searchTerm.length == 0) return true; if (propertyObject.name.toLowerCase().indexOf(searchTerm) !== -1) return true; if ('keywords' in propertyObject) { for (var keyword of propertyObject.keywords) { if (keyword.toLowerCase().indexOf(searchTerm) !== -1) return true; } } for (var valueObj of propertyObject.values) { if (valueObj.value.toLowerCase().indexOf(searchTerm) !== -1) return true; } return false; } function getSpecificationCategory(propertyObject) { if ('specification' in propertyObject) { var specification = propertyObject.specification; if ('category' in specification) { return specification.category; } } return undefined; } function getSpecificationObsoleteCategory(propertyObject) { if ('specification' in propertyObject) { var specification = propertyObject.specification; if ('obsolete-category' in specification) { return specification['obsolete-category']; } } return undefined; } function isCategoryMatch(propertyObject, categories) { if (!categories.length) return true; var category; if (category = getSpecificationCategory(propertyObject)) { if (categories.indexOf(category) !== -1) { return true; } } if (category = getSpecificationObsoleteCategory(propertyObject)) { if (categories.indexOf(category) !== -1) { return true; } } return false; } function propertyOrAliasIsPrefixed(propertyObject) { if (prefixRegexp.exec(propertyObject.name)) return true; for (var alias of propertyNameAliases(propertyObject)) { if (prefixRegexp.exec(alias)) return true; } return false; } function isStatusFiltered(propertyObject, activeFilters) { if (activeFilters.length == 0) return true; if (propertyObject.status === undefined) return false; if (activeFilters.indexOf(propertyObject.status.status) !== -1) return true; return false; } function isPrefixFiltered(propertyObject, activeFilters) { if (activeFilters.length == 0) return true; if (activeFilters.indexOf('prefix-only-property') !== -1) return prefixRegexp.exec(propertyObject.name); if (activeFilters.indexOf('prefix-supported-property') !== -1) return propertyOrAliasIsPrefixed(propertyObject); if (activeFilters.indexOf('prefix-supported-value') !== -1) { for (var valueObj of propertyObject.values) { if (valueOrAliasIsPrefixed(valueObj)) return true; } } if (activeFilters.indexOf('prefix-only-value') !== -1) { for (var valueObj of propertyObject.values) { if (prefixRegexp.exec(valueObj.value)) return true; } } return false; } function findValueByName(values, name) { return values.find(function(element) { return element.value === name; }) } function mergeProperties(unprefixedPropertyObj, prefixedPropertyObj) { (unprefixedPropertyObj['codegen-properties'].aliases = unprefixedPropertyObj['codegen-properties'].aliases || []).push(prefixedPropertyObj.name); var prefixedValues = Array.from(prefixedPropertyObj.values); for (var valueObj of prefixedValues) { if (!findValueByName(unprefixedPropertyObj.values, valueObj.value)) prefixedPropertyObj.values.push(valueObj); } return unprefixedPropertyObj; } // Sometimes we have separate entries for -webkit-foo and foo. function collapsePrefixedProperties(properties) { function findPropertyByName(properties, name) { return properties.find(function(element) { return element.name === name; }) } var remainingProperties = []; var prefixMap = {}; for (var propertyObj of properties) { var propertyName = propertyObj.name; var result = prefixRegexp.exec(propertyName); if (result) { var unprefixed = result[2]; var unprefixedProperty = findPropertyByName(properties, unprefixed); if (unprefixedProperty) { mergeProperties(unprefixedProperty, propertyObj); continue; } } remainingProperties.push(propertyObj); } return remainingProperties; } function canonicalizeValues(propertyObject) { var valueObjects = []; // Convert all values to objects. if ('values' in propertyObject) { for (var value of propertyObject.values) { if (typeof value === 'object') valueObjects.push(value); else valueObjects.push({ 'value' : value }); } } propertyObject.values = valueObjects; } function canonicalizeStatus(propertyObject, categories) { // Inherit "status" from the category if not explicitly specified. if (!('status' in propertyObject)) { var category = getSpecificationCategory(propertyObject) if (category) { var categoryObject = categories[category]; if (categoryObject) { if ('status' in categoryObject) { propertyObject.status = { 'status' : categoryObject.status }; } } } } else { // Convert all values to objects. if (typeof propertyObject.status === 'string') propertyObject.status = { 'status': propertyObject.status }; } if (!('status' in propertyObject)) { propertyObject.status = { 'status' : 'supported', 'enabled-by-default' : true }; } else if (!('status' in propertyObject.status)) propertyObject.status.status = 'supported'; propertyObject.status.status = canonicalizeIdentifier(propertyObject.status.status); } function renderContent(results) { var mainContent = document.getElementById("property-list"); var successSubtree = document.importNode(document.getElementById("success-template").content, true); mainContent.appendChild(successSubtree); var properties = results[0]['properties']; var everythingToShow = []; var categories = results[0]['categories']; for (var property in properties) { var propertyObject = properties[property]; propertyObject.name = property; canonicalizeValues(propertyObject); canonicalizeStatus(propertyObject, categories); everythingToShow.push(propertyObject); } everythingToShow = collapsePrefixedProperties(everythingToShow); sortAlphabetically(everythingToShow); renderProperties(categories, everythingToShow); initSearch(everythingToShow, categories); updateSearch(everythingToShow); } function displayError(error) { window.console.log('displayError', error) var mainContent = document.getElementById("property-list"); var successSubtree = document.importNode(document.getElementById("error-template").content, true); var errorMessage = "Unable to load " + error.url; if (error.request.status !== 200) { errorMessage += ", status: " + error.request.status + " - " + error.request.statusText; } else if (!error.response) { errorMessage += ", the JSON file cannot be processed."; } successSubtree.querySelector("#error-message").textContent = errorMessage; mainContent.appendChild(successSubtree); } Promise.all([loadCSSProperties]).then(renderContent).catch(displayError); } document.addEventListener("DOMContentLoaded", initializeStatusPage); </script> </div><!--.page-width--> </main><!-- #content --> <footer> <div class="page-width"> <nav id="footer-nav" aria-label="Footer menu"><div class="menu-footer-menu-container"><ul id="menu-footer-menu" class="menu"><li id="menu-item-7617" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-7617"><a rel="me" href="https://front-end.social/@webkit">@webkit@front-end.social</a></li> <li id="menu-item-5365" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-5365"><a href="https://webkit.org/sitemap/">Site Map</a></li> <li id="menu-item-4185" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4185"><a href="http://www.apple.com/legal/privacy/">Privacy Policy</a></li> <li id="menu-item-4287" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4287"><a href="https://webkit.org/licensing-webkit/">Licensing WebKit</a></li> <li id="menu-item-4187" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4187"><a href="https://webkit.org/terms-of-use/">WebKit and the WebKit logo are trademarks of Apple Inc.</a></li> </ul></div></nav> </div> </footer> <script type="text/javascript" src="https://webkit.org/wp-content/themes/webkit/scripts/global.js?ver=1.0" id="theme-global-js"></script> </body> </html> <!-- Dynamic page generated in 0.359 seconds. --> <!-- Cached page generated by WP-Super-Cache on 2024-11-23 11:52:21 --> <!-- super cache -->

Pages: 1 2 3 4 5 6 7 8 9 10