-- BigQuery query for HTTP Archive CSS + HTML observables -- Generated: 2026-02-18 -- Scans parsed_css ONCE for CSS properties, selectors, and at-rules -- Scans pages for HTML element usage via custom_metrics.element_count -- Uses efficient single-scan approach with REGEXP_EXTRACT_ALL on JSON strings DECLARE crawl_date DATE DEFAULT '2026-01-01'; -- ============================================================================= -- LOOKUP TABLES: observable names and their web-feature ID mappings -- ============================================================================= WITH css_property_lookup AS ( SELECT * FROM UNNEST([ STRUCT('align-content' AS observable, 'flexbox,grid,align-content-block' AS feature_ids), STRUCT('align-items' AS observable, 'flexbox,grid,anchor-positioning' AS feature_ids), STRUCT('align-self' AS observable, 'flexbox,grid,anchor-positioning' AS feature_ids), STRUCT('display' AS observable, 'flexbox,grid,display-animation,mathml,two-value-display' AS feature_ids), STRUCT('flex' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-basis' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-direction' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-flow' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-grow' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-shrink' AS observable, 'flexbox' AS feature_ids), STRUCT('flex-wrap' AS observable, 'flexbox' AS feature_ids), STRUCT('justify-content' AS observable, 'flexbox,grid' AS feature_ids), STRUCT('justify-items' AS observable, 'flexbox,grid,anchor-positioning' AS feature_ids), STRUCT('order' AS observable, 'flexbox' AS feature_ids), STRUCT('place-content' AS observable, 'flexbox,grid' AS feature_ids), STRUCT('place-items' AS observable, 'flexbox,grid,anchor-positioning' AS feature_ids), STRUCT('place-self' AS observable, 'flexbox,grid,anchor-positioning' AS feature_ids), STRUCT('position' AS observable, 'flexbox' AS feature_ids), STRUCT('outline' AS observable, 'outline' AS feature_ids), STRUCT('column-gap' AS observable, 'flexbox-gap,grid' AS feature_ids), STRUCT('gap' AS observable, 'flexbox-gap,grid' AS feature_ids), STRUCT('row-gap' AS observable, 'flexbox-gap,grid' AS feature_ids), STRUCT('appearance' AS observable, 'appearance,customizable-select' AS feature_ids), STRUCT('background-clip' AS observable, 'background-clip-text' AS feature_ids), STRUCT('clip-path' AS observable, 'clip-path,clip-path-boxes' AS feature_ids), STRUCT('grid' AS observable, 'grid' AS feature_ids), STRUCT('grid-area' AS observable, 'grid' AS feature_ids), STRUCT('grid-auto-columns' AS observable, 'grid' AS feature_ids), STRUCT('grid-auto-flow' AS observable, 'grid' AS feature_ids), STRUCT('grid-auto-rows' AS observable, 'grid' AS feature_ids), STRUCT('grid-column' AS observable, 'grid' AS feature_ids), STRUCT('grid-column-end' AS observable, 'grid' AS feature_ids), STRUCT('grid-column-start' AS observable, 'grid' AS feature_ids), STRUCT('grid-row' AS observable, 'grid' AS feature_ids), STRUCT('grid-row-end' AS observable, 'grid' AS feature_ids), STRUCT('grid-row-start' AS observable, 'grid' AS feature_ids), STRUCT('grid-template' AS observable, 'grid' AS feature_ids), STRUCT('grid-template-areas' AS observable, 'grid' AS feature_ids), STRUCT('grid-template-columns' AS observable, 'grid,subgrid' AS feature_ids), STRUCT('grid-template-rows' AS observable, 'grid,subgrid' AS feature_ids), STRUCT('justify-self' AS observable, 'grid,anchor-positioning' AS feature_ids), STRUCT('scrollbar-width' AS observable, 'scrollbar-width' AS feature_ids), STRUCT('will-change' AS observable, 'will-change' AS feature_ids), STRUCT('text-indent' AS observable, 'text-indent' AS feature_ids), STRUCT('mask' AS observable, 'masks' AS feature_ids), STRUCT('mask-clip' AS observable, 'masks' AS feature_ids), STRUCT('mask-composite' AS observable, 'masks' AS feature_ids), STRUCT('mask-image' AS observable, 'masks' AS feature_ids), STRUCT('mask-mode' AS observable, 'masks' AS feature_ids), STRUCT('mask-origin' AS observable, 'masks' AS feature_ids), STRUCT('mask-position' AS observable, 'masks' AS feature_ids), STRUCT('mask-repeat' AS observable, 'masks' AS feature_ids), STRUCT('mask-size' AS observable, 'masks' AS feature_ids), STRUCT('block-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('border-block' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-end' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-end-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-end-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-end-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-start' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-start-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-start-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-start-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-block-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-end-end-radius' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-end-start-radius' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-end' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-end-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-end-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-end-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-start' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-start-color' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-start-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-start-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-style' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-inline-width' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-start-end-radius' AS observable, 'logical-properties' AS feature_ids), STRUCT('border-start-start-radius' AS observable, 'logical-properties' AS feature_ids), STRUCT('clear' AS observable, 'logical-properties' AS feature_ids), STRUCT('float' AS observable, 'logical-properties' AS feature_ids), STRUCT('inline-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-block' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-block-end' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-block-start' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-inline' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-inline-end' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('inset-inline-start' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-block' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-block-end' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-block-start' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-inline' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-inline-end' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('margin-inline-start' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('max-block-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('max-inline-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('min-block-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('min-inline-size' AS observable, 'logical-properties,anchor-positioning' AS feature_ids), STRUCT('overflow-block' AS observable, 'logical-properties' AS feature_ids), STRUCT('overflow-inline' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-block' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-block-end' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-block-start' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-inline' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-inline-end' AS observable, 'logical-properties' AS feature_ids), STRUCT('padding-inline-start' AS observable, 'logical-properties' AS feature_ids), STRUCT('forced-color-adjust' AS observable, 'forced-colors' AS feature_ids), STRUCT('aspect-ratio' AS observable, 'aspect-ratio' AS feature_ids), STRUCT('backdrop-filter' AS observable, 'backdrop-filter' AS feature_ids), STRUCT('text-wrap' AS observable, 'text-wrap,text-wrap-balance,text-wrap-pretty' AS feature_ids), STRUCT('overflow-x' AS observable, 'overflow-clip,overflow-shorthand' AS feature_ids), STRUCT('overflow-y' AS observable, 'overflow-clip,overflow-shorthand' AS feature_ids), STRUCT('overflow' AS observable, 'overflow-clip,overflow-shorthand' AS feature_ids), STRUCT('color-scheme' AS observable, 'color-scheme' AS feature_ids), STRUCT('rotate' AS observable, 'individual-transforms' AS feature_ids), STRUCT('scale' AS observable, 'individual-transforms' AS feature_ids), STRUCT('translate' AS observable, 'individual-transforms' AS feature_ids), STRUCT('scrollbar-color' AS observable, 'scrollbar-color' AS feature_ids), STRUCT('text-underline-offset' AS observable, 'text-underline-offset' AS feature_ids), STRUCT('scroll-margin' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-block' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-block-end' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-block-start' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-bottom' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-inline' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-inline-end' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-inline-start' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-left' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-right' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-margin-top' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-block' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-block-end' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-block-start' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-bottom' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-inline' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-inline-end' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-inline-start' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-left' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-right' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-padding-top' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-snap-align' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-snap-stop' AS observable, 'scroll-snap' AS feature_ids), STRUCT('scroll-snap-type' AS observable, 'scroll-snap' AS feature_ids), STRUCT('container' AS observable, 'container-queries' AS feature_ids), STRUCT('container-name' AS observable, 'container-queries' AS feature_ids), STRUCT('container-type' AS observable, 'container-queries,container-scroll-state-queries' AS feature_ids), STRUCT('scrollbar-gutter' AS observable, 'scrollbar-gutter' AS feature_ids), STRUCT('hyphens' AS observable, 'hyphens' AS feature_ids), STRUCT('quotes' AS observable, 'quotes' AS feature_ids), STRUCT('content-visibility' AS observable, 'content-visibility,display-animation' AS feature_ids), STRUCT('contain-intrinsic-block-size' AS observable, 'contain-intrinsic-size' AS feature_ids), STRUCT('contain-intrinsic-height' AS observable, 'contain-intrinsic-size' AS feature_ids), STRUCT('contain-intrinsic-inline-size' AS observable, 'contain-intrinsic-size' AS feature_ids), STRUCT('contain-intrinsic-size' AS observable, 'contain-intrinsic-size' AS feature_ids), STRUCT('contain-intrinsic-width' AS observable, 'contain-intrinsic-size' AS feature_ids), STRUCT('border-image' AS observable, 'border-image' AS feature_ids), STRUCT('border-image-outset' AS observable, 'border-image' AS feature_ids), STRUCT('border-image-repeat' AS observable, 'border-image' AS feature_ids), STRUCT('border-image-slice' AS observable, 'border-image' AS feature_ids), STRUCT('border-image-source' AS observable, 'border-image' AS feature_ids), STRUCT('border-image-width' AS observable, 'border-image' AS feature_ids), STRUCT('line-break' AS observable, 'line-break' AS feature_ids), STRUCT('transform-box' AS observable, 'transform-box' AS feature_ids), STRUCT('animation-range' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('animation-range-end' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('animation-range-start' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('animation-timeline' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('animation' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('scroll-timeline' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('scroll-timeline-axis' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('scroll-timeline-name' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('timeline-scope' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('view-timeline' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('view-timeline-axis' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('view-timeline-inset' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('view-timeline-name' AS observable, 'scroll-driven-animations' AS feature_ids), STRUCT('interpolate-size' AS observable, 'interpolate-size' AS feature_ids), STRUCT('print-color-adjust' AS observable, 'print-color-adjust' AS feature_ids), STRUCT('box-decoration-break' AS observable, 'box-decoration-break' AS feature_ids), STRUCT('accent-color' AS observable, 'accent-color' AS feature_ids), STRUCT('font-optical-sizing' AS observable, 'font-optical-sizing' AS feature_ids), STRUCT('text-spacing-trim' AS observable, 'text-spacing-trim' AS feature_ids), STRUCT('font-size-adjust' AS observable, 'font-size-adjust' AS feature_ids), STRUCT('font-synthesis' AS observable, 'font-synthesis' AS feature_ids), STRUCT('field-sizing' AS observable, 'field-sizing' AS feature_ids), STRUCT('paint-order' AS observable, 'paint-order' AS feature_ids), STRUCT('font-size' AS observable, 'mathml' AS feature_ids), STRUCT('math-depth' AS observable, 'mathml' AS feature_ids), STRUCT('math-shift' AS observable, 'mathml' AS feature_ids), STRUCT('math-style' AS observable, 'mathml' AS feature_ids), STRUCT('text-transform' AS observable, 'mathml' AS feature_ids), STRUCT('text-box' AS observable, 'text-box' AS feature_ids), STRUCT('text-box-edge' AS observable, 'text-box' AS feature_ids), STRUCT('text-box-trim' AS observable, 'text-box' AS feature_ids), STRUCT('white-space-collapse' AS observable, 'white-space-collapse' AS feature_ids), STRUCT('transition-behavior' AS observable, 'transition-behavior' AS feature_ids), STRUCT('transition' AS observable, 'transition-behavior' AS feature_ids), STRUCT('view-transition-name' AS observable, 'view-transitions' AS feature_ids), STRUCT('counter-set' AS observable, 'counter-set' AS feature_ids), STRUCT('font-language-override' AS observable, 'font-language-override' AS feature_ids), STRUCT('background-image' AS observable, 'image-set' AS feature_ids), STRUCT('content' AS observable, 'image-set' AS feature_ids), STRUCT('offset' AS observable, 'motion-path' AS feature_ids), STRUCT('offset-anchor' AS observable, 'motion-path' AS feature_ids), STRUCT('offset-distance' AS observable, 'motion-path' AS feature_ids), STRUCT('offset-path' AS observable, 'motion-path' AS feature_ids), STRUCT('offset-position' AS observable, 'motion-path' AS feature_ids), STRUCT('offset-rotate' AS observable, 'motion-path' AS feature_ids), STRUCT('animation-composition' AS observable, 'animation-composition' AS feature_ids), STRUCT('anchor-name' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('anchor-scope' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('bottom' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('height' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('left' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('margin-bottom' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('margin-left' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('margin-right' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('margin-top' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('margin' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('max-height' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('max-width' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('min-height' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('min-width' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-anchor' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-area' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-try' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-try-fallbacks' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-try-order' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('position-visibility' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('right' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('top' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('width' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('font-variant-alternates' AS observable, 'font-variant-alternates' AS feature_ids), STRUCT('text-justify' AS observable, 'text-justify' AS feature_ids), STRUCT('hyphenate-character' AS observable, 'hyphenate-character' AS feature_ids), STRUCT('font-variant-position' AS observable, 'font-variant-position' AS feature_ids), STRUCT('text-emphasis' AS observable, 'text-emphasis' AS feature_ids), STRUCT('text-emphasis-color' AS observable, 'text-emphasis' AS feature_ids), STRUCT('text-emphasis-position' AS observable, 'text-emphasis' AS feature_ids), STRUCT('text-emphasis-style' AS observable, 'text-emphasis' AS feature_ids), STRUCT('image-orientation' AS observable, 'image-orientation' AS feature_ids), STRUCT('ruby-position' AS observable, 'ruby-position' AS feature_ids), STRUCT('ruby-align' AS observable, 'ruby-align' AS feature_ids), STRUCT('hyphenate-limit-chars' AS observable, 'hyphenate-limit-chars' AS feature_ids), STRUCT('font-synthesis-weight' AS observable, 'font-synthesis-weight' AS feature_ids), STRUCT('text-wrap-style' AS observable, 'text-wrap-style' AS feature_ids), STRUCT('initial-letter' AS observable, 'initial-letter' AS feature_ids), STRUCT('view-transition-class' AS observable, 'view-transition-class' AS feature_ids), STRUCT('font-variant-emoji' AS observable, 'font-variant-emoji' AS feature_ids), STRUCT('font-palette' AS observable, 'font-palette,font-palette-animation' AS feature_ids), STRUCT('font-family' AS observable, 'font-family-math' AS feature_ids), STRUCT('scroll-marker-group' AS observable, 'scroll-markers' AS feature_ids), STRUCT('word-break' AS observable, 'word-break-auto-phrase' AS feature_ids), STRUCT('overlay' AS observable, 'overlay' AS feature_ids), STRUCT('object-view-box' AS observable, 'object-view-box' AS feature_ids), STRUCT('contain' AS observable, 'contain-inline-size' AS feature_ids), STRUCT('reading-flow' AS observable, 'reading-flow' AS feature_ids), STRUCT('reading-order' AS observable, 'reading-flow' AS feature_ids), STRUCT('font-synthesis-style' AS observable, 'font-synthesis-style' AS feature_ids), STRUCT('direction' AS observable, 'vertical-form-controls' AS feature_ids), STRUCT('writing-mode' AS observable, 'vertical-form-controls' AS feature_ids), STRUCT('interactivity' AS observable, 'interactivity' AS feature_ids), STRUCT('baseline-source' AS observable, 'baseline-source' AS feature_ids), STRUCT('scroll-initial-target' AS observable, 'scroll-initial-target' AS feature_ids), STRUCT('font-synthesis-small-caps' AS observable, 'font-synthesis-small-caps' AS feature_ids) ]) ), css_selector_lookup AS ( SELECT * FROM UNNEST([ STRUCT('not' AS observable, 'not' AS feature_ids, ':not' AS search_pattern), STRUCT('slotted' AS observable, 'slot' AS feature_ids, '::slotted' AS search_pattern), STRUCT('focus-visible' AS observable, 'focus-visible' AS feature_ids, ':focus-visible' AS search_pattern), STRUCT('has' AS observable, 'has' AS feature_ids, ':has' AS search_pattern), STRUCT('where' AS observable, 'where' AS feature_ids, ':where' AS search_pattern), STRUCT('is' AS observable, 'is' AS feature_ids, ':is' AS search_pattern), STRUCT('marker' AS observable, 'marker' AS feature_ids, '::marker' AS search_pattern), STRUCT('nesting' AS observable, 'nesting' AS feature_ids, '&' AS search_pattern), STRUCT('file-selector-button' AS observable, 'file-selector-button' AS feature_ids, '::file-selector-button' AS search_pattern), STRUCT('dir' AS observable, 'dir-pseudo' AS feature_ids, ':dir' AS search_pattern), STRUCT('cue' AS observable, 'webvtt' AS feature_ids, '::cue' AS search_pattern), STRUCT('nth-child' AS observable, 'nth-child-of' AS feature_ids, ':nth-child' AS search_pattern), STRUCT('nth-last-child' AS observable, 'nth-child-of' AS feature_ids, ':nth-last-child' AS search_pattern), STRUCT('modal' AS observable, 'modal' AS feature_ids, ':modal' AS search_pattern), STRUCT('autofill' AS observable, 'autofill' AS feature_ids, ':autofill' AS search_pattern), STRUCT('backdrop' AS observable, 'popover' AS feature_ids, '::backdrop' AS search_pattern), STRUCT('popover-open' AS observable, 'popover' AS feature_ids, ':popover-open' AS search_pattern), STRUCT('view-transition' AS observable, 'view-transitions' AS feature_ids, '::view-transition' AS search_pattern), STRUCT('view-transition-group' AS observable, 'view-transitions' AS feature_ids, '::view-transition-group' AS search_pattern), STRUCT('view-transition-image-pair' AS observable, 'view-transitions' AS feature_ids, '::view-transition-image-pair' AS search_pattern), STRUCT('view-transition-new' AS observable, 'view-transitions' AS feature_ids, '::view-transition-new' AS search_pattern), STRUCT('view-transition-old' AS observable, 'view-transitions' AS feature_ids, '::view-transition-old' AS search_pattern), STRUCT('grammar-error' AS observable, 'spelling-grammar-error' AS feature_ids, '::grammar-error' AS search_pattern), STRUCT('spelling-error' AS observable, 'spelling-grammar-error' AS feature_ids, '::spelling-error' AS search_pattern), STRUCT('details-content' AS observable, 'details-content' AS feature_ids, '::details-content' AS search_pattern), STRUCT('user-invalid' AS observable, 'user-pseudos' AS feature_ids, ':user-invalid' AS search_pattern), STRUCT('user-valid' AS observable, 'user-pseudos' AS feature_ids, ':user-valid' AS search_pattern), STRUCT('future' AS observable, 'time-relative-selectors' AS feature_ids, ':future' AS search_pattern), STRUCT('past' AS observable, 'time-relative-selectors' AS feature_ids, ':past' AS search_pattern), STRUCT('state' AS observable, 'state' AS feature_ids, ':state' AS search_pattern), STRUCT('active-view-transition' AS observable, 'active-view-transition' AS feature_ids, ':active-view-transition' AS search_pattern), STRUCT('active-view-transition-type' AS observable, 'active-view-transition' AS feature_ids, ':active-view-transition-type' AS search_pattern), STRUCT('target-text' AS observable, 'target-text' AS feature_ids, '::target-text' AS search_pattern), STRUCT('highlight' AS observable, 'highlight' AS feature_ids, '::highlight' AS search_pattern), STRUCT('scroll-marker' AS observable, 'scroll-markers' AS feature_ids, '::scroll-marker' AS search_pattern), STRUCT('scroll-marker-group' AS observable, 'scroll-markers' AS feature_ids, '::scroll-marker-group' AS search_pattern), STRUCT('picture-in-picture' AS observable, 'picture-in-picture' AS feature_ids, ':picture-in-picture' AS search_pattern), STRUCT('checkmark' AS observable, 'customizable-select' AS feature_ids, '::checkmark' AS search_pattern), STRUCT('picker' AS observable, 'customizable-select' AS feature_ids, '::picker' AS search_pattern), STRUCT('picker-icon' AS observable, 'customizable-select' AS feature_ids, '::picker-icon' AS search_pattern), STRUCT('scroll-button' AS observable, 'scroll-buttons' AS feature_ids, '::scroll-button' AS search_pattern), STRUCT('xr-overlay' AS observable, 'webxr-dom-overlays' AS feature_ids, ':xr-overlay' AS search_pattern), STRUCT('column' AS observable, 'column-pseudo' AS feature_ids, '::column' AS search_pattern), STRUCT('has-slotted' AS observable, 'has-slotted' AS feature_ids, ':has-slotted' AS search_pattern), STRUCT('selection' AS observable, 'text-decoration-selection' AS feature_ids, '::selection' AS search_pattern) ]) ), css_atrule_lookup AS ( SELECT * FROM UNNEST([ STRUCT('media' AS observable, 'forced-colors,prefers-contrast,display-mode,media-query-range-syntax,dynamic-range,prefers-reduced-transparency,device-posture,update,scripting,overflow' AS feature_ids), STRUCT('container' AS observable, 'container-queries,container-style-queries,container-scroll-state-queries' AS feature_ids), STRUCT('view-transition' AS observable, 'cross-document-view-transitions' AS feature_ids), STRUCT('font-face' AS observable, 'font-metric-overrides,font-size-adjust' AS feature_ids), STRUCT('property' AS observable, 'registered-custom-properties' AS feature_ids), STRUCT('import' AS observable, 'cascade-layers' AS feature_ids), STRUCT('layer' AS observable, 'cascade-layers' AS feature_ids), STRUCT('starting-style' AS observable, 'starting-style' AS feature_ids), STRUCT('page' AS observable, 'page-orientation' AS feature_ids), STRUCT('position-try' AS observable, 'anchor-positioning' AS feature_ids), STRUCT('font-feature-values' AS observable, 'font-variant-alternates' AS feature_ids), STRUCT('counter-style' AS observable, 'counter-style' AS feature_ids), STRUCT('scope' AS observable, 'scope' AS feature_ids), STRUCT('font-palette-values' AS observable, 'font-palette' AS feature_ids) ]) ), html_element_lookup AS ( SELECT * FROM UNNEST([ STRUCT('slot' AS observable, 'slot' AS feature_ids), STRUCT('canvas' AS observable, 'canvas' AS feature_ids), STRUCT('a' AS observable, 'referrer-policy,attribution-reporting,fencedframe,scroll-to-text-fragment' AS feature_ids), STRUCT('area' AS observable, 'referrer-policy,attribution-reporting' AS feature_ids), STRUCT('iframe' AS observable, 'referrer-policy,attribution-reporting,storage-access,screen-wake-lock,compute-pressure,accelerometer,window-management,iframe-credentialless,idle-detection,web-otp,picture-in-picture,web-midi,webusb,serial,webhid,local-fonts,gamepad,web-bluetooth' AS feature_ids), STRUCT('img' AS observable, 'referrer-policy,fetch-priority,aspect-ratio,attribution-reporting,sizes-auto' AS feature_ids), STRUCT('link' AS observable, 'referrer-policy,fetch-priority,manifest,blocking-render,link-rel-expect,compression-dictionary-transport' AS feature_ids), STRUCT('script' AS observable, 'referrer-policy,fetch-priority,js-modules,attribution-reporting,speculation-rules,blocking-render,import-maps' AS feature_ids), STRUCT('video' AS observable, 'aspect-ratio,remote-playback,picture-in-picture' AS feature_ids), STRUCT('template' AS observable, 'template,declarative-shadow-dom' AS feature_ids), STRUCT('meta' AS observable, 'color-scheme,meta-application-title' AS feature_ids), STRUCT('style' AS observable, 'blocking-render' AS feature_ids), STRUCT('dialog' AS observable, 'dialog,dialog-closedby' AS feature_ids), STRUCT('button' AS observable, 'popover,anchor-positioning' AS feature_ids), STRUCT('input' AS observable, 'popover,anchor-positioning' AS feature_ids), STRUCT('datalist' AS observable, 'datalist' AS feature_ids), STRUCT('fencedframe' AS observable, 'fencedframe' AS feature_ids), STRUCT('audio' AS observable, 'remote-playback' AS feature_ids), STRUCT('search' AS observable, 'search' AS feature_ids), STRUCT('details' AS observable, 'details-name' AS feature_ids), STRUCT('selectedcontent' AS observable, 'customizable-select' AS feature_ids) ]) ), -- ============================================================================= -- SINGLE SCAN of parsed_css: extract properties, selector blocks, and at-rule types -- Converts the css JSON column to a string ONCE per row, then extracts all three -- categories in a single pass over the table. -- ============================================================================= css_raw AS ( SELECT page, TO_JSON_STRING(css) AS css_str FROM `httparchive.crawl.parsed_css` WHERE date = crawl_date AND client = 'desktop' AND is_root_page = TRUE ), -- Extract distinct CSS properties per page page_css_properties AS ( SELECT page, prop FROM css_raw, UNNEST(REGEXP_EXTRACT_ALL(css_str, r'"property":"([^"]+)"')) AS prop GROUP BY page, prop ), -- Extract selector blocks per page (the content inside "selectors":[...]) -- Each sel_block is a string like '"h1","h2",".foo:not(.bar)"' page_css_selectors AS ( SELECT page, sel_block FROM css_raw, UNNEST(REGEXP_EXTRACT_ALL(css_str, r'"selectors":\[([^\]]+)\]')) AS sel_block GROUP BY page, sel_block ), -- Extract distinct at-rule types per page page_css_atrules AS ( SELECT page, atrule FROM css_raw, UNNEST(REGEXP_EXTRACT_ALL(css_str, r'"type":"([^"]+)"')) AS atrule GROUP BY page, atrule ), -- ============================================================================= -- CSS PROPERTY RESULTS: join extracted properties with lookup -- ============================================================================= css_property_results AS ( SELECT lk.feature_ids, lk.observable, 'css_property' AS type, COUNT(DISTINCT pcp.page) AS pages_using FROM css_property_lookup lk LEFT JOIN page_css_properties pcp ON pcp.prop = lk.observable GROUP BY lk.feature_ids, lk.observable ), -- ============================================================================= -- CSS SELECTOR RESULTS: search selector blocks for patterns -- For each page, check if any selector block contains the search pattern -- ============================================================================= css_selector_results AS ( SELECT lk.feature_ids, lk.observable, 'css_selector' AS type, COUNT(DISTINCT pcs.page) AS pages_using FROM css_selector_lookup lk LEFT JOIN page_css_selectors pcs ON pcs.sel_block LIKE CONCAT('%', lk.search_pattern, '%') GROUP BY lk.feature_ids, lk.observable ), -- ============================================================================= -- CSS AT-RULE RESULTS: join extracted at-rule types with lookup -- ============================================================================= css_atrule_results AS ( SELECT lk.feature_ids, lk.observable, 'css_atrule' AS type, COUNT(DISTINCT pca.page) AS pages_using FROM css_atrule_lookup lk LEFT JOIN page_css_atrules pca ON pca.atrule = lk.observable GROUP BY lk.feature_ids, lk.observable ), -- ============================================================================= -- HTML ELEMENTS: extract from custom_metrics.element_count in pages table -- element_count is a JSON object like {"div": 500, "span": 200, "dialog": 1} -- ============================================================================= page_html_elements AS ( SELECT page, LOWER(elem_name) AS elem_name FROM `httparchive.crawl.pages`, UNNEST( REGEXP_EXTRACT_ALL( TO_JSON_STRING(custom_metrics.element_count), r'"([^"]+)"\s*:' ) ) AS elem_name WHERE date = crawl_date AND client = 'desktop' AND is_root_page = TRUE GROUP BY page, elem_name ), html_element_results AS ( SELECT lk.feature_ids, lk.observable, 'html_element' AS type, COUNT(DISTINCT phe.page) AS pages_using FROM html_element_lookup lk LEFT JOIN page_html_elements phe ON phe.elem_name = lk.observable GROUP BY lk.feature_ids, lk.observable ), -- ============================================================================= -- TOTAL PAGES: for computing percentages -- ============================================================================= total_css_pages AS ( SELECT COUNT(DISTINCT page) AS total_pages FROM `httparchive.crawl.parsed_css` WHERE date = crawl_date AND client = 'desktop' AND is_root_page = TRUE ), total_html_pages AS ( SELECT COUNT(DISTINCT page) AS total_pages FROM `httparchive.crawl.pages` WHERE date = crawl_date AND client = 'desktop' AND is_root_page = TRUE ), -- ============================================================================= -- COMBINE all results -- ============================================================================= all_results AS ( SELECT feature_ids, observable, type, pages_using FROM css_property_results UNION ALL SELECT feature_ids, observable, type, pages_using FROM css_selector_results UNION ALL SELECT feature_ids, observable, type, pages_using FROM css_atrule_results UNION ALL SELECT feature_ids, observable, type, pages_using FROM html_element_results ) SELECT r.feature_ids, r.observable, r.type, r.pages_using, CASE WHEN r.type = 'html_element' THEN th.total_pages ELSE tc.total_pages END AS total_pages, SAFE_DIVIDE(r.pages_using * 100.0, CASE WHEN r.type = 'html_element' THEN th.total_pages ELSE tc.total_pages END ) AS pct FROM all_results r CROSS JOIN total_css_pages tc CROSS JOIN total_html_pages th ORDER BY pct DESC;