1 पॉइंट द्वारा GN⁺ 4 일 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • CSS selectors और declarations संरचनात्मक रूप से Datalog के काफ़ी करीब हैं, क्योंकि वे पहले से मौजूद elements के एक set को चुनते हैं और उस result पर properties लागू करते हैं; Datalog भी relations को query करके facts बनाता है
  • सामान्य CSS selection result को दोबारा selection condition के रूप में इस्तेमाल करने वाली recursive computation को support नहीं करता, इसलिए वह ऐसी state propagation को सीधे व्यक्त नहीं कर सकता जिसमें dark theme descendants तक फैले लेकिन light boundary पर रुक जाए
  • काल्पनिक CSSLog में ऐसी class जोड़ने की अनुमति होगी जो selector matching को प्रभावित करे, जिससे .effectively-dark जैसी derived state को recursively propagate किया जा सके, और computation तब तक दोहराई जाए जब तक कोई नया result न बचे
  • इस तरह की computation को Datalog के fixpoint और monotonicity से समझाया जाता है; iteration के finitely खत्म होने के लिए facts को हटाने के बजाय सिर्फ़ जोड़ना चाहिए
  • वास्तविक CSS की container queries ancestor state को पढ़ तो सकती हैं, लेकिन derived recursive state को query नहीं कर सकतीं; इसलिए CSS, Datalog के क़रीब पहुँचकर भी browser rendering engine की सीमा पार नहीं करता

CSS और Datalog का बुनियादी correspondence

  • CSS पहले से मौजूद targets को मानकर चलता है, और यहाँ वे target HTML elements हैं
    • h1, a, div जैसे elements CSS के बाहर पहले से मौजूद होते हैं; CSS उन्हें नया declare नहीं करता
    • उदाहरण के तौर पर class, id, data-custom-attribute जैसी attributes वाले elements दिखाए गए हैं
  • CSS selectors साझा conditions वाले set को दर्शाते हैं, और tag name, id, class, attribute value से target को सीमित कर सकते हैं
    • div, #child, .awesome, [data-custom-attribute="foo"] जैसे selectors उदाहरण में आते हैं
    • document hierarchy के अंदर position relationship से भी target व्यक्त किया जा सकता है, और selectors को जोड़कर intersection भी बनाया जा सकता है
  • div.awesome जैसा combined selector set intersection करता है, यानी सिर्फ़ वे elements चुने जाते हैं जो div भी हों और .awesome भी
    • यही intersection आगे चलकर Datalog के join से जुड़ने वाली अहम अवधारणा बनती है
  • CSS rule selector और declaration को जोड़कर चुने गए set पर property values लागू करता है
    • div.awesome { color: red; font-size: 24px } उदाहरण में उन elements का color और font-size सेट होता है
    • browser में उसका result बड़े लाल text के रूप में render होता है

CSS की सीमाएँ और recursive query की समस्या

  • सामान्य CSS language के बाहर की properties बदलने में मज़बूत है, लेकिन उन बदलावों के result को फिर सीधे selection condition के रूप में इस्तेमाल नहीं कर सकता
    • element का color सेट किया जा सकता है, लेकिन div[color=red] की तरह color को ही selector condition बनाना browser अस्वीकार कर देता है
    • color: red वाले element पर फिर color: blue लगाने वाला rule अर्थ की दृष्टि से अस्पष्ट हो जाएगा
  • design system का dark mode उदाहरण transitive state propagation की माँग करने वाली समस्या के रूप में दिया गया है
    • data-theme="dark" वाले card के अंदर सभी interactive elements पर white focus outline लागू करनी है
    • लेकिन बीच में data-theme="light" आ जाए तो उसके नीचे propagation रुक जानी चाहिए
  • वास्तविक CSS में exceptions जोड़ने के तरीके से सिर्फ़ कुछ हद तक इसे संभाला जा सकता है
    • [data-theme="dark"] :focus { outline-color: white; } से base rule बनाया जा सकता है
    • [data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } से light boundary को वापस पलटा जा सकता है
    • लेकिन nesting गहरी होती जाए तो नए rules लगातार जोड़ने पड़ते हैं
  • इस समस्या के लिए recursive relational definition चाहिए, लेकिन CSS उसे व्यक्त नहीं कर सकता
    • परिभाषा कुछ ऐसी चाहिए: “या तो वह ख़ुद dark हो, या उसका कोई effectively-dark ancestor हो और बीच में कोई effectively-light ancestor न हो, तब वह effectively-dark है”
    • मूल लेख इसे recursive relational definition कहता है और साफ़ कहता है कि CSS इसे व्यक्त नहीं कर सकता

CSSLog की काल्पनिक syntax

  • CSSLog को सामान्य CSS की तरह selectors और property setting बनाए रखते हुए, उन properties को बदलने वाला काल्पनिक version बताया गया है जो selector matching को प्रभावित करती हैं
    • उदाहरण में class: +bar जैसा class जोड़ने वाला syntax आता है
    • +<div class="baz"> जैसी form से नया child element बनाने की भी कल्पना की गई है
    • element deletion के बारे में सिर्फ़ इतना लिखा है कि “शायद नहीं होना चाहिए”, अतिरिक्त विवरण नहीं है
  • div.foo rule चलने के बाद वही element div.bar से भी match करने लगे, इस तरह rule execution का result अगली matching को प्रभावित करता है
    • यहाँ computation एक बार के forward application पर खत्म नहीं होती, बल्कि repeated evaluation की ज़रूरत पड़ती है
  • dark mode उदाहरण को CSSLog में लाने पर derived class की recursive propagation संभव हो जाती है
    • [data-theme="dark"] { class: +effectively-dark; } से शुरुआत होती है
    • .effectively-dark > :not([data-theme="light"]) { class: +effectively-dark; } से यह children तक propagate होता है
    • .effectively-dark :focus { outline-color: white; } से अंतिम style लागू होती है
  • दूसरा rule light boundary तक recursively propagate करता है और desired state आने पर रुक जाता है
    • मूल लेख कहता है कि मौजूदा CSS से ऐसा behavior संभव नहीं है, और अंत में कुछ मिलते-जुलते workarounds पर फिर लौटता है

Datalog की संरचना और CSS से समानता

  • Datalog में targets को atoms कहा जाता है, और वे पहली बार उल्लेख होते ही अस्तित्व में माने जाते हैं
    • alice, bob जैसे नाम बिना अलग declaration के सीधे इस्तेमाल होते हैं
    • साथ में Ruby के :symbols से तुलना भी की गई है
  • sets और relationships को relations और tuples से व्यक्त किया जाता है
    • parent(alice, bob) parent relation के भीतर एक tuple है
    • parent को उन जोड़ियों के set के रूप में समझाया गया है जहाँ पहला target दूसरे target का parent है
  • variables का इस्तेमाल query matching और set selection के लिए होता है
    • parent(bob, X) का मतलब है वे सभी X जिनके parent Bob हैं
    • इस उदाहरण में X का result carol और dave आता है
    • प्रथा के तौर पर variables uppercase में और atoms व relations lowercase में लिखे जाते हैं
  • वही variable name दोहराने पर join होता है
    • mother(X, Y) :- parent(X, Y), woman(X). parent set और woman set के intersection से mother relation बनाता है
    • लेख इसे “सभी parents” और “सभी women” के intersection की तरह समझाता है
  • Datalog rule का :- if की तरह पढ़ा जाता है; जब दाहिनी ओर के body conditions सब सच हों, तब बाईं ओर का head fact true के रूप में जोड़ा जाता है
    • body में comma को and की तरह पढ़ा जाता है
    • ancestor(X, Y) :- parent(X, Y). का अर्थ है: अगर X, Y का parent है, तो X उसका ancestor है
  • CSS और Datalog की तुलना उलटी हुई लेकिन समान संरचना के रूप में की गई है
    • color(X, red) :- div(X), class(X, awesome). का अर्थ होगा “जो X div है और awesome class रखता है, उसका color red है”
    • इसे CSS के div.awesome { color: red; } के semantic counterpart के रूप में दिखाया गया है
    • मूल लेख निष्कर्ष निकालता है कि selector body है और declaration head

Recursion और derived facts

  • Datalog में कुछ “करने” का मतलब नए facts derive करना है
    • यह existing facts के आधार पर relation में नए tuples जोड़कर काम करता है
  • ancestor उदाहरण recursive rule का आदर्श मामला है
    • ancestor(X, Y) :- parent(X, Y). direct parent को ancestor बनाता है
    • ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y). parent के ancestor relation का पीछा करते हुए ऊपर तक फैलाता है
  • दूसरा rule ancestor के head और body दोनों में आने वाली self-referential recursion रखता है
    • इससे alice -> bob -> carol, alice -> bob -> dave जैसी indirect ancestor relationships derive होती हैं
  • उदाहरण के execution result में ये पाँच facts दिए गए हैं
    • ancestor(alice, bob)
    • ancestor(bob, carol)
    • ancestor(bob, dave)
    • ancestor(alice, carol)
    • ancestor(alice, dave)
  • SQL भी WITH RECURSIVE से पहले ऐसी computation नहीं कर पाता था, और लेख के अनुसार यह feature recursive computation की माँग के कारण आया
    • हालाँकि लेख यह भी जोड़ता है कि SQL की recursive syntax और semantics हमेशा बाकी हिस्सों के साथ अच्छी तरह compose नहीं होतीं
  • Datalog में for loop के बिना भी engine जब तक सारे ज़रूरी results न निकल आएँ तब तक computation जारी रखता है
    • अगला section इसका कारण fixpoint से जोड़ता है

Fixpoint और monotonicity

  • सामान्य CSS का cascade एक बार की forward application की तरह बताया गया है
    • browser rules पढ़ता है, selector matching compute करता है, declarations लागू करता है, और काम खत्म हो जाता है
    • कोई feedback loop नहीं होता
  • CSSLog और वास्तविक Datalog में किसी rule का result दूसरे rule की condition को फिर से satisfy करा सकता है
    • कोई rule property बदलता है, उसी property की वजह से दूसरा rule फिर चल सकता है, और फिर उसका असर पहले rule तक भी लौट सकता है
  • एक naïve Datalog engine जब तक कोई नया fact न बचे तब तक rules को बार-बार लागू करता है
    • वह declared base facts से शुरू करता है
    • सभी rules के body को मौजूदा facts के set से match करता है
    • match होने पर head fact जोड़ता है
    • नया fact मिले तो फिर दोहराता है, नहीं मिले तो रुक जाता है
  • इस रुकने की स्थिति को fixpoint कहा जाता है
    • यानी वह state जहाँ सभी rules फिर से चलाने पर भी कोई नया result नहीं निकलता
  • ancestor उदाहरण को तीन rounds में समझाया गया है
    • पहले round में parent facts से direct ancestor relation के तीन facts जुड़ते हैं
    • दूसरे round में alice के दो indirect ancestor relations जुड़ते हैं
    • तीसरे round में कोई नया fact नहीं बनता और fixpoint आ जाता है
  • termination संभव होने का कारण monotonicity है
    • facts हटाए नहीं जाते, सिर्फ़ जोड़े जाते हैं; इसलिए known facts का set लगातार बढ़ता ही है
    • finite starting facts और finite derivation possibilities होने पर finite काम के बाद रुकना संभव है
  • उल्टा, अगर facts हटाने की अनुमति हो तो बाद के result पहले के result को पलट सकते हैं, और यह गुण टूट जाता है
    • मूल लेख इसे Infinite Loop Land कहता है, और इसी से जोड़कर बताता है कि CSSLog में element deletion की अनुमति न देना बेहतर होगा
  • footnote में यह भी जोड़ा गया है कि distributed systems में monotonicity महँगे coordination के बिना consistency पाने के गुण से जुड़ी होती है

यह महत्वपूर्ण क्यों है

  • CSS और Datalog की तुलना अलग-अलग क्षेत्रों में एक ही संरचना को उजागर करती है
    • दोनों में targets होते हैं, उन targets के sets को query किया जाता है, और फिर result के आधार पर कुछ लागू किया जाता है या नए facts बनाए जाते हैं
  • Datalog और Prolog 1970 के दशक से relational databases और उस समय के AI research में दिखाई देते रहे हैं, और बाद में कई रूपों में फिर उभरे
  • इसमें यह observation है कि अगर आप ऐसा system बनाते हैं जिसमें targets हों, sets को describe करने की क्षमता हो, और उन targets पर operations किए जा सकें, तो वह समान निष्कर्षों की ओर converge करता है
  • database/logic programming और frontend web development के क्षेत्र अक्सर एक-दूसरे से नहीं जुड़ते
    • लेख उम्मीद जताता है कि अगर ये ज़्यादा जुड़ें तो मिलकर कुछ नया बनाया जा सकता है

Container Queries और वास्तविक CSS की सीमा

  • यह चर्चा वास्तविक CSS feature Container Queries से भी जुड़ती है
    • इनके ज़रिए parent या ancestor element की style के आधार पर current element पर style लागू की जा सकती है
    • उदाहरण के रूप में @container style(--theme: dark) { .card { background: royalblue; color: white; } } दिया गया है
  • लेकिन transitive dark mode की समस्या सिर्फ़ ancestor lookup से अधिक शक्तिशाली computation माँगती है
    • हर element को पता होना चाहिए कि वह effectively dark है या नहीं
    • वह state descendants तक transitively propagate होनी चाहिए
    • और data-theme="light" boundary पर propagation रुकनी चाहिए
  • Container queries derived state को नहीं पढ़ सकतीं
    • वे ancestor की custom property value देख सकती हैं, लेकिन किसी दूसरे rule द्वारा पहले से compute की गई effectively-dark जैसी state को query नहीं कर सकतीं
    • वे सिर्फ़ DOM में पहले से मौजूद state पढ़ सकती हैं; recursive computation का result नहीं
  • इसलिए “अगर कोई ancestor transitively dark है और उससे अधिक नज़दीक कोई light ancestor नहीं है, तो apply करो” जैसी query recursion माँगती है, इसलिए implement नहीं की जा सकती
    • मूल लेख साफ़ कहता है कि container queries में recursion नहीं है
  • 2015 article में बताया गया है कि element queries मिलते-जुलते कारणों से बार-बार क्यों विफल हुईं
    • अगर query जिन properties को सेट करती है, उन्हीं को फिर query किया जा सके, तो loops और आगे चलकर infinite loops बन सकते हैं
  • CSS Working Group ने ऐसी समस्याओं को information flow की direction सीमित करके हल किया है
    • descendants ancestors की जानकारी query कर सकते हैं, लेकिन उलटी दिशा नहीं
    • इससे fixpoint semantics के बिना भी finiteness बनाए रखी जा सकती है
    • information सिर्फ़ tree के नीचे की दिशा में propagate होती है और structure ऐसा रहता है कि कोई नए base facts नहीं डाले जाते
  • मूल लेख इस प्रवाह को ऐसे दिखाता है कि CSS, Datalog engine के क़रीब पहुँचते हुए भी जानबूझकर वहाँ तक नहीं जाता
    • CSSLog का पक्ष चक्रों की अनुमति देकर fixpoint तक evaluate करने का है
    • जबकि वास्तविक CSS इस सीमा पर रुकता है कि browser rendering engine कोई incremental relational database engine नहीं है

दूसरी दिशा की संभावनाएँ

  • browser में Datalog semantics डालने के बजाय, Datalog के ऊपर CSS syntax चढ़ाने की दिशा भी संभव है
    • Datalog का :-, period, uppercase/lowercase conventions, assignment statements का अभाव जैसी बातें आधुनिक language users के लिए entry barrier बन सकती हैं
  • CSS के पास पहले से tree structure को सीधे संभालने वाली syntax है
    • descendant, child, sibling combinators parent-child relation को स्वाभाविक रूप से व्यक्त करते हैं
    • साधारण Datalog में ऐसी संरचना को relational form में कुछ असुविधाजनक तरीके से encode करना पड़ता है
  • लेख ज़ोर देता है कि बहुत-सा वास्तविक data tree form में होता है
    • JSON
    • AST
    • file system
    • org chart
    • XML उदाहरण के रूप में सूचीबद्ध हैं
  • अगर कोई tool fixpoint recursion, CSS-style syntax और implicit parent-child relationships को जोड़ दे, तो recursive tree queries अधिक परिचित notation में लिखी जा सकती हैं
  • लेख के अनुसार अब तक शायद किसी ने ऐसा tool ठीक से नहीं बनाया है
    • अंत में यह सुझाव दिया गया है कि कोई व्यक्ति बेहतर नाम वाले “CSSLog” जैसा कुछ बना सकता है

Footnotes

  • HTML elements की simplification पर एक footnote है
    • संभावित आपत्ति यह हो सकती है that CSS जिन targets से काम करता है वे सभी ज़रूरी नहीं कि सिर्फ़ HTML elements हों, लेकिन लेख में सरलता के लिए उन्हें HTML elements मान लिया गया है
  • naive evaluation हर बार पहले से known facts को भी फिर compute करती है, इसलिए inefficient होती है
    • standard improvement के रूप में semi-naive evaluation का उल्लेख है
    • इसका मूल विचार यह है कि हर चरण में सिर्फ़ नए derive हुए facts देखे जाएँ
  • यह भी जोड़ा गया है कि infinite loops Turing-complete languages में कोई अनोखी बात नहीं हैं
    • JavaScript में भी while true {} लिखा जा सकता है
    • लेकिन web page की logic confusion की वजह से browser rendering system हमेशा के लिए रुक जाए, यह स्थिति टालना बेहतर है
  • CSS की custom property inheritance workaround पर भी footnote में चर्चा है
    • [data-theme="dark"] { --effective-theme: dark; }
    • [data-theme="light"] { --effective-theme: light; }
    • @container style(--effective-theme: dark) { :focus { outline-color: white; } }
    • यह तरीका इस खास case में काफ़ी हद तक काम करता है, लेकिन inheritance असली transitive closure के बराबर नहीं है
    • अधिक जटिल समस्याओं में, जहाँ parent-child के अलावा किसी और property chain के साथ transitive closure चाहिए, यह तरीका टूट जाता है

1 टिप्पणियां

 
GN⁺ 4 일 전
Hacker News टिप्पणियाँ
  • CSS selectors को XPath की तुलना में लिखना बहुत आसान है
    हाल ही में PHP के नए DOM API पर एक प्रस्तुति भी थी, जिसमें बताया गया कि अब HTML और CSS selectors को native तौर पर बहुत आसानी से हैंडल किया जा सकता है। पहले CSS को XPath में बदलना पड़ता था
    [1] https://speakerdeck.com/keyvan/parsing-html-with-php-8-dot-4...
    अफ़सोस है कि यह ब्राउज़र styling-केंद्रित तरीके से विकसित हुआ, इसलिए इसमें XPath जैसी text content आधारित selection जैसी सुविधाएँ नहीं हैं
    मुझे पता है कि पहले इसके प्रस्ताव आए थे, लेकिन ब्राउज़र rendering context में performance समस्याएँ आ सकती थीं, इसलिए शायद यह spec में शामिल नहीं हो पाया

    • LLM भी CSS selectors को काफ़ी अच्छी तरह संभाल लेते हैं
      एक document editing agent बनाते समय मैंने दस्तावेज़ को HTML के रूप में दिखाया और LLM से सिर्फ़ CSS selector निर्दिष्ट करवाकर ज़रूरी हिस्से context में खींचने दिए, और यह लगभग जादू की तरह काम करता था
    • client side पर querySelector/querySelectorAll इतने व्यापक रूप से इस्तेमाल होते हैं, इसलिए PHP के नए DOM में उनका आना अच्छा लगा
      लोग उसी परिचित तरीके से इसे इस्तेमाल कर सकते हैं
  • काश CSS grammar और CSSWG द्वारा परिभाषित rules, functions, units जैसी पूरी प्रणाली को अलग से बुलाने के लिए कोई नाम होता
    इसमें काफ़ी संभावना है, लेकिन दूसरे use cases पर बात करने या उन्हें खोजने के लिए आख़िरकार GitHub के उस कोड को खंगालना पड़ता है जिसमें CSS parser शामिल हो, ताकि पता चल सके कि लोग कैसी अजीब चीज़ें बना रहे हैं
    मैं कुछ वैसा भी छेड़छाड़ कर रहा हूँ जो किसी अजीब template engine जैसा है, जिसमें हल्की node-आधारित markup language, template में क्या जाएगा यह व्यक्त करने वाले CSS selectors, और इन टुकड़ों को कैसे जोड़ा जाए इसे नियंत्रित करने वाला CSS-जैसा grammar मिला हुआ है

    • मुझे लगता है कि standards में यह विभाजन पहले से काफ़ी साफ़ है
      https://www.w3.org/TR/selectors-3/
      DOM spec भी इसी का संदर्भ देती है
      https://dom.spec.whatwg.org/#selectors
      इसलिए CSS selector एक umbrella term के रूप में पहले से सही है, और इसे सिर्फ़ selector भी कहा जा सकता है
      DOM selector नाम और साफ़ लग सकता है, लेकिन अगर static CSS में इस्तेमाल होने वाले selectors या JS engine के बाहर के दूसरे DOM engines (XML parser, PHP DOM API आदि) के selectors को भी सोचें, तो यह उल्टा और भ्रमित कर सकता है
      साथ ही :hover या ::target-text जैसे ऐसे special selectors भी हैं जो सीधे ब्राउज़र rendering/navigation से जुड़े हैं
      फिर भी, ब्राउज़र या CSS से कम जुड़े हुए न्यूनतम query grammar subset के लिए अलग नाम होना उपयोगी हो सकता है
  • मुझे पुराने conference में देखा हुआ https://github.com/braposo/graphql-css याद आ गया
    यह मज़ाकिया project था, लेकिन यह अच्छी तरह दिखाता था कि patterns को दूसरे contexts में transplant करके दोबारा इस्तेमाल करने का तरीका अप्रत्याशित चीज़ों को संभव बना सकता है

    • यह मज़ेदार है
      मैं भी ठीक इसी तरह अलग contexts के patterns उठाकर आज़माने की कोशिश कर रहा हूँ
      ज़्यादातर चीज़ें शायद कहीं दूर तक न जाएँ, फिर भी hacker संवेदना के हिसाब से यह काफ़ी दिलचस्प है
  • pyastgrep में, जैसा कि https://pyastgrep.readthedocs.io/en/latest/ पर दिखता है, Python grammar को query करने के लिए CSS selectors इस्तेमाल किए जा सकते हैं
    default XPath है, और उदाहरण के लिए pyastgrep --css 'Call > func > Name#main' जैसा इस्तेमाल संभव है

    • यह वाकई बहुत अच्छा है
      यह लगभग ठीक उसी दिशा से मेल खाता है जिसकी ओर मैं इशारा करना चाहता था
  • मुझे ठीक से समझ नहीं आ रहा कि यह किस scenario को हल करता है
    अभी भी child के आधार पर parent को conditionally बदला जा सकता है। उदाहरण के लिए pre की default padding 16px है, और अगर उसका direct child code है तो &:has(> code) से इसे 0 किया जा सकता है

    • दरअसल यह शुरुआत में इस बात से निकला था कि दो अलग ideas एक-दूसरे से मिलते-जुलते लगते हैं, और फिर उस connection को कई दिशाओं में धकेलकर देखने जैसा बन गया
      निष्कर्ष भी "आधुनिक CSS की सीमाओं को ठीक करना चाहिए" से ज़्यादा इस बात के करीब है कि शायद CSS-जैसा grammar किसी Datalog-जैसी system पर चढ़ाने से tree-आकृति वाले data को संभालना ज़्यादा इंजीनियरों के लिए परिचित बनाया जा सकता है
    • यहाँ बात एक style calculation में हल होने वाली चीज़ की नहीं, बल्कि selector से match हुए target के underlying data को ही modify करने वाले grammar की है
      यानी बात DOM में नए child elements या attributes जोड़ने की है
  • मौजूदा LLM CSS को बहुत अच्छी तरह नहीं संभालते, इसलिए उल्टा यह आज़माकर देखना दिलचस्प होगा कि क्या इससे LLM ज़्यादा सरल तरीके से reason कर पाते हैं

  • इसका कोई वास्तविक उपयोग तुरंत नहीं सूझता, लेकिन यह फिर भी काफ़ी cool है

  • हम्म... कहीं यह बस JQ तो नहीं है?

  • मुझे CSS कुछ हद तक पसंद है, लेकिन इसकी बढ़ती हुई complexity creep पसंद नहीं
    मैं समझता हूँ कि programming languages, non-programming languages से ज़्यादा शक्तिशाली हो जाती हैं, लेकिन HTML, CSS और JavaScript को लगातार और जटिल बनाने की बजाय शायद बेहतर होता कि कुछ और आकर पूरे सेट को replace कर देता
    HTML5 के नए elements भी क्यों ज़रूरी हैं, यह मुझे ज़्यादातर समझ नहीं आता, इसलिए मैं उन्हें शायद ही कभी इस्तेमाल करता हूँ। आख़िर में कई containers बस unique ID लगे div ही लगते हैं, और कभी-कभी लगता था कि internal link के लिए href navigation हेतु उन IDs के aliases जैसे कुछ होने चाहिए थे
    [data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } जैसी चीज़ को दिमाग़ में parse करने में बहुत समय लगता है, इसलिए यह अब elegant या simple नहीं लगती
    दूसरी तरफ़ h2 { color: red; } अब भी simple है
    ancestor(X, Y) :- parent(X, Y). जैसा expression देखते ही सोचने का मन नहीं करता। :- आख़िर है क्या, मुस्कुराते चेहरे जैसा दिखता है
    @container style(--theme: dark) { .card { background: royalblue; color: white; } } पर तो मैंने पढ़ना ही छोड़ दिया
    अजीब लगता है कि जो standard पहले ठीक काम करता था, वह समय के साथ बिगड़ता जा रहा है

    • मेरा इरादा CSS में और syntax व semantics जोड़ने का नहीं, बल्कि CSS से ideas चुराकर logic/relational query language के साथ उसकी समानता का उपयोग करते हुए कुछ नया बनाने के ज़्यादा करीब है
      उदाहरण के लिए [data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } को अंग्रेज़ी जैसी pseudocode में खोलें तो इसका मतलब लगभग यह है कि अगर data-theme="dark" वाला X है, उसका child Y data-theme="light" है, और वह focus स्थिति में है, तो Y का outline-color black कर दो
      इसलिए इसे Datalog शैली में outline-color(Y, black) if data-theme(X, "dark") and parent(X, Y) and data-theme(Y, "light") and focused(Y) की तरह लिखा जा सकता है
      यानी :- को if से और comma को and से बदलने जैसा
      इससे आगे जाकर इसे Y.outline_color := black if X.data-theme == dark and Y.parent == X and Y.data-theme == dark and Y.focused की तरह भी लिखा जा सकता है, ताकि attr(X, val) को X.attr == val जैसी UFCS-जैसी syntax sugar की तरह दिखाया जा सके
      अगर इसे और ALGOL परिवार जैसा बनाना हो, तो forall Y { Y.outline_color := black if Y.data_theme == "dark" and Y.focused and Y.parent.data_theme == "light" } जैसा भी लिखा जा सकता है
      यहाँ Y को explicitly introduce किया गया है और एक join को implicit बना दिया गया है, जिससे यह ज़्यादा सामान्य programming जैसा दिखता है, लेकिन असल में Datalog engine dependencies बदलने पर हर बार ऐसे loop को efficiently चलाता है