Chris’ Corner: Esoteric Stuff in CSS

Listen I ain’t trying to scare you, but this CSS stuff can get complicated. It doesn’t have to be. CSS is just selectors with key value pairs in the end. The vast majority of CSS I write is pretty darn straightforward, especially once you have a general system (what files go where? how do we generally name things? how do we do variables?). But fair is fair, CSS can get wildly complex. It doesn’t help the complexity situation that anything new added increases that complexity, because, well, everything in CSS affects everything else. Selectors can get confusing and nesting can exacerbate that. Variables can get changed at any time and it’s not always clear from where. The situation on the page (sizing, events, settings) can effect what’s happening in CSS in increasingly bigger ways (querying containers, querying user preferences). If you want to push the edges of what CSS can do, now is the time.

I often save links of other people’s explorations of these edges of CSS. They are fascinating to me, naturally, as one of the proprietors of a front-end coding tool and ex-owner of CSS-Tricks. But sometimes I struggle to find a way to share them and contextualize them because of the complexity. In fact I think it’s fair to not use techniques based on complexity alone, after all, you write it you maintain it.

But let’s remove the limiter and look at CSS stuff regardless of how complex it might be.


I’ll start with one that has broken my brain for a few years now. @James0x57 calls this technique “Space Toggles” (who credits Ana Tudor for the discovery). Lea Verou calls it The -​-var: ; hack. Just to lock in my own understanding, I called it The CSS Custom Property Toggle Trick.

The idea is that CSS custom properties can be valid and invalid, a valid value even just being " " (a single space). You can concatenate that custom property with others to produce either-valid-or-invalid other custom properties. If it’s valid, you can do one thing, if it’s invalid, you can use the fallback for the custom property to do another thing. So it’s essentially if/then logic for custom properties.

The closest I ever came to simplifying it is this. And I admit it’s not exactly straightforward.

The good news is that CSS just decided that if() would be a thing, so now we wait for browser implementations. It should be quite a bit more straightforward, although the ease-of-use will lead to more exotic usage of it and, I’m afraid to admit, more complex CSS.


Have you ever prepped for needing to do a sorting algorithm in a job interview? Can you explain what a Bubble Sort is? It’s the one where you loop through a list comparing the two things next to each other, and swap them if they need to be swapped. You keep running through the list until you don’t do any more swaps. I think, anyway, I’m not some computer genius over here. GrahamTheDev is though! Their article Bubble Sort…in PURE CSS? is bonkers.

It literally works.

This is the complexity that comes through the ability to compare variables (e.g. we have min() and max() in CSS now) and set new variables based on other variables. Write enough of that with delays and animations and you got yourself a bubble sort. Good luck grokking all that though.

And speaking of the edges of CSS:

warning: on mobile the last few animations might not play and just go blank. On PC your fan may spin up!

This is a limitation of using so many calculations that rely on previous calculations…I am not sure if it runs out of memory or what, but I defo pushed the limits of CSS here!


What’s the value of cos(25deg) in CSS? Tyler Gaw wanted to figure it out exactly.

I know that will return a number between -1 and 1. But what number?

You can’t even set any property to exactly that, because just the number it produces is invalid for most properties.

You can do something like width: calc(1px * cos(25deg)) then check the width value in the devtools computed styles panel and get close, but not exact. Also, width: cos(25deg) is invalid CSS and using a custom prop like --v: cos(25deg) doesn’t really work either because the custom prop value is stored as cos(25deg).

But obviously cos(25deg) produces a number?! Tyler found a way to extract the CSS-generated number in JavaScript. I felt like having a poke at it too, but I didn’t get much further. I did discover that the output is a unitless number, so it’s valid for CSS properties that take unitless numbers, like line-height. So you can set line-height directly with it and then read the computed value. The problem is the computed value isn’t the direct output of the cos() function it’s the final px value so… blech, hard.


There is some CSS trickery that involves @keyframe animations. For example, styles applied during an animation apply extra strongly, so a style applied with a animation that runs for, say, a year is a way to do style overrides. Not recommended, heh. Setting animations to a particular place and pausing them is another weird trick for managing state in CSS.

Those, at least, I feel like I can get my brain around quickly. Animations have some extra power (and complexity) lately via Scroll-Driven Animations. Roman Komarov is the master recently of extremely exotic and complex CSS trickery, and his Scroll-Driven State Transfer is the pièce de résistance.

… an ability to mirror a particular state of some element — for example, hovered or focused — to an element in a different place on the page without a common or unique ancestral element that could have been used to deliver that state

You might think of :has() as the new hotness for being able to access state anywhere in CSS from anywhere else, and you’d be right, but apparently this trick is a bit more adaptable, not requiring us to write more CSS later:

… we could implement this with the :has() selector, but for any new values we’d have to modify the stylesheet afterwards

It looks like the trick involves those Space Toggles too, meaning I think this is one of the most complicated CSS tricks I’ve ever seen. Apart from the super math-y stuff that always blows my mind, that is.


We’ve established that animations can be one of the vehicles for CSS complexity, which is true when using them just to animate, not strong-arm them into some wild state machine.

One way animations can get complicated is combining them. It was just the other day I reminded myself that nesting elements and then animating them both essentially doubles the speed of the inside animation. That’s just shooting a cannon from an airplane though, no fancy tech there. CSS actually allows us to manually combine animations, with tools like animation-composition. It can be confusing though! Bramus wrote up The mysterious case of using CSS animation-composition: accumulate on a scale transform outlining just how weird it can get even in relatively simple situations. Maybe you’ll scratch your head too:

Accumulating a scale(0.5) with scale(2) does not give scale(2.5) but scale(1.5)

After scratching my own head about this long enough, it did sort of start to make sense. Even though blur(2) and blur(3) certainly make blur(5) when accumulated, those are both “blur something more”. In the case of scale, 0.5 makes something smaller. So adding 2.0 + 0.5 isn’t 2.5 because they aren’t both “do something more”, one is “make smaller” and one is “make bigger”, hence the spec having to step in and explain.

Global Deadlock Resolution in GBase 8c Transactions and Locks

GBase 8c database features mechanisms for deadlock detection and automatic resolution. It comprises multiple CNs (Coordinating Nodes) and DN (Data Nodes). Deadlocks can occur within a single CN or DN, or across multiple CNs or DNs. Deadlocks occurring across multiple CNs or DNs are termed global deadlocks, where processes across multiple databases in the cluster cyclically wait for resources. This article primarily discusses distributed global deadlock resolution.

Screenshot_2024-06-24_at_18.18.24.png

As depicted in the figure above, at time T1, Transaction 1 begins (begin), at T2, Transaction 1 updates (update) the t column for id=1, while Transaction 2 begins. At T3, Transaction 2 updates the t column for id=4. Subsequently, at T4, Transaction 1 attempts to update the t value for id=4, and Transaction 2 attempts to update id=1's t value, resulting in mutual waiting and thus a global deadlock.

Global deadlock detection algorithms mainly fall into two categories: centralized and distributed:

1. Centralized: The GTM node (Global Transaction Manager) collects transaction lock wait information from other nodes in the cluster to construct a global wait-for graph. It then queries for deadlock cycles (using algorithms like depth-first search or topological sorting) and issues commands to terminate transactions involved in deadlocks. This approach can overload the GTM node, potentially becoming a cluster performance bottleneck. Moreover, if the GTM node encounters issues, deadlock detection becomes ineffective, making this approach less recommended.

2. Distributed: (Currently used in GBase 8c) Each CN initiates deadlock detection independently. Detection messages propagate along the wait-for relationships among transaction processing threads across nodes. If a transaction processing thread receives its own detection message, it indicates a global deadlock, prompting the transaction to rollback and resolve the deadlock.

Screenshot_2024-06-24_at_18.18.24.png

Example:

When Transaction 1 detects that data it wishes to update is locked by another transaction, it sends a waiting message to the node holding the lockin this example, CN2, where Transaction 2 originated. Similarly, Transaction 2, upon finding that the data it needs is locked by Transaction 1, sends a waiting message to CN1, where Transaction 1 is running. The transactions wait for a predetermined timeout period. If the waiting cycle is detected by either node within this period, the node initiating the detection exits its transaction, thereby resolving the global deadlock.

Testing Method:

The default deadlock timeout is 1 second, modified to 20 seconds:

show deadlock_timeout ;
alter system set deadlock_timeout=20

Create Test Table

create table test(id int,info text);
insert into test values(1,'Tom');
insert into test values(2,'Lane');

session1, Execute Update

begin;
update test set info = 'test' where id = 1;

session2, Execute Update

begin;
update test set info = 'test' where id = 2;

session1, Execute Update

update test set info = 'test' where id = 2;  --stuck

session2, Execute Update

update test set info = 'test' where id = 1;  --stuck

After 20 seconds, one session's transaction detects and terminates the deadlock, while the other session successfully commits.

Migration from GaussDB to GBase 8a: Clients, Third-Party Tools, and APIs

1. Comparison Between GSQL and GCCLI Clients

GSQL is a database connection tool provided by GaussDB 200 for running commands in the command line. This tool allows you to connect to the server and perform operations and maintenance. Its functionalities include: connecting to the database, executing SQL statements, executing meta-commands, and directly setting and using variables.

GBase 8a MPPs GCCLI supports connecting to the database and executing SQL but does not support directly setting and using variables.

Variables set in GaussDB must be executed in stored procedures when using GBase 8a data:

gsql -h 10.180.123.163 -d postgres -U jack -p 25308 
\set foo 'HR.areaS' 
select * from :foo; 
area_id | area_name 
---------+------------------------ 
4 | Middle East and Africa 
3 | Asia 
1 | Europe 
2 | Americas 
(4 rows)
2. Data Studio and GBase Studio

Data Studio is a GUI tool that allows you to connect to the database, execute, and debug SQL statements and stored procedures. Data Studio supports the basic features of GaussDB 200 and provides a graphical interface for database developers. The corresponding tool for GBase 8a MPP is GBase Studio.

3. Migration of Other Third-Party Tools and Application Interfaces

Similar to GaussDB, GBase 8a supports the use of standard database interface APIs such as JDBC, ODBC, Perl DBI, and Python DBI. For detailed information on the installation and configuration of specific interfaces, refer to the relevant API interface manuals provided by GBase 8a.

If third-party tools or programs that use the aforementioned API interfaces to access GaussDB are to be migrated to GBase 8a database, this can be done by conventionally configuring the connection driver.

Common third-party tools supported by GBase 8a include:

  • ETL Tools: Kettle, Informatica
  • BI Tools: Cognos, Tableau
  • Analytical Tools: SAS, SPSS

For detailed information on integrating specific tools, refer to the integration manuals provided by GBase 8a.

Celebrating the Trailblazers: International Women in Engineering Day 2024

As we approach International Women in Engineering Day on June 23, 2024, we must recognize women's remarkable achievements and invaluable contributions to engineering. 

This global awareness campaign, celebrated annually, aims to highlight the accomplishments of women engineers and encourage more women to pursue careers in this dynamic and impactful industry. In this article, we bring together the insights and experiences of several exceptional women in technology who share their thoughts on the significance of this day and the importance of promoting diversity in the tech industry.

MaxLinear Empowers High-Speed Connectivity and Data Acceleration Solutions for Next-Gen Computing

MaxLinear, a leading provider of high-performance analog and mixed-signal integrated circuits, recently presented their advanced networking and connectivity solutions at the 56th IT Press Tour. The company showcased its innovative products designed to support the massive data transmission requirements of distributed computing architectures.

Transforming Communications With Mixed-Signal Expertise

Founded in 2003, MaxLinear has a rich history of building communication products that leverage their expertise in analog and mixed-signal design. By integrating complex analog and digital functions on a single chip, MaxLinear enables faster and more efficient connectivity solutions.

Books To Start Your Career in Cloud, DevOps, or SRE in 2024

I am an avid reader of technical books, specifically those focused on Cloud, DevOps, and Site Reliability Engineering (SRE). In this post, I will share a list of books that I believe are essential for anyone looking to start or advance their career in Cloud, DevOps, or SRE. These books will help you build a strong foundation in the top skills required in these fields. While this post focuses primarily on Amazon AWS for public cloud, I will also include a few vendor-neutral books.

Note: This is my honest opinion, and I am not affiliated with any of these book authors or publishers.

Automate Message Queue Deployment on JBoss EAP

For decades now, software projects have relied on messaging APIs to exchange data. In the Java/Java EE ecosystem, this method of asynchronous communication has been standardized by the JMS specification. In many cases, individuals and organizations leverage Red Hat JBoss Enterprise Application Platform (JBoss EAP) to act as message-oriented middleware (MOM), which facilitates the management of message queues and topics.

Messaging ensures that no messages are lost as they are transmitted from the client and delivered to interested parties. On top of that, JBoss EAP provides authentication and other security-focused capabilities on top of the management functions.

Block Size and Its Impact on Storage Performance

This article analyzes the correlation between block sizes and their impact on storage performance. This paper deals with definitions and understanding of structured data vs unstructured data, how various storage segments react to block size changes, and differences between I/O-driven and throughput-driven workloads. It also highlights the calculation of throughput and the choice of storage product based on workload type. 

Block Size and Its Importance

In computing, a physical record or data storage block is a sequence of bits/bytes referred to as a block. The amount of data processed or transferred in a single block within a system or storage device is referred to as the block size. It is one of the deciding factors for storage performance. Block size is a crucial element in performance benchmarking for storage products and categorizing the products into block, file, and object segments.

MDX Or: How I Learned To Stop Worrying And Love Multimedia Writing

Prior to the World Wide Web, the act of writing remained consistent for centuries. Words were put on paper, and occasionally, people would read them. The tools might change — quills, printing presses, typewriters, pens, what have you — and an adventurous author may perhaps throw in imagery to compliment their copy.

We all know that the web shook things up. With its arrival, writing could become interactive and dynamic. As web development progressed, the creative possibilities of digital content grew — and continue to grow — exponentially. The line between web writing and web technologies is blurry these days, and by and large, I think that’s a good thing, though it brings its own challenges. As a sometimes-engineer-sometimes-journalist, I straddle those worlds more than most and have grown to view the overlap as the future.

Writing for the web is different from traditional forms of writing. It is not a one-size-fits-all process. I’d like to share the benefits of writing content in digital formats like MDX using a personal project of mine as an example. And, by the end, my hope is to convince you of the greater writing benefits of MDX over more traditional formats.

A Little About Markdown

At its most basic, MDX is Markdown with components in it. For those not in the know, Markdown is a lightweight markup language created by John Gruber in 2003, and it’s everywhere today. GitHub, Trello, Discord — all sorts of sites and services use it. It’s especially popular for authoring blog posts, which makes sense as blogging is very much the digital equivalent of journaling. The syntax doesn’t “get in the way,” and many content management systems support it.

Markdown’s goal is an “easy-to-read and easy-to-write plain text format” that can readily be converted into XHTML/HTML if needed. Since its inception, Markdown was supposed to facilitate a writing workflow that integrated the physical act of writing with digital publishing.

We’ll get to actual examples later, but for the sake of explanation, compare a block of text written in HTML to the same text written in Markdown.

HTML is a pretty legible format as it is:

<h2>Post Title</h2>

<p>This is an example block of text written in HTML. We can link things up like this, or format the code with <strong>bolding</strong> and <em>italics</em>. We can also make lists of items:</p>

<ul>
  <li>Like this item<li>
  <li>Or this one</li>
  <li>Perhaos a third?</li>
</ul>

<img src="image.avif" alt="And who doesn't enjoy an image every now and then?">

But Markdown is somehow even less invasive:

## Post Title

This is an example block of text written in HTML. We can link things up like this or format the code with **bolding** and *italics*. We can also make lists of items:

- Like this item
- Or this one
- Perhaos a third?


I’ve become a Markdown disciple since I first learned to code. Its clean and relatively simple syntax and wide compatibilities make it no wonder that Markdown is as pervasive today as it is. Having structural semantics akin to HTML while preserving the flow of plain text writing is a good place to be.

However, it could be accused of being a bit too clean at times. If you want to communicate with words and images, you’re golden, but if you want to jazz things up, you’ll find yourself looking further afield for other options.

Gruber set out to create a “format for writing for the web,” and given its ongoing popularity, you have to say he succeeded, yet the web 20 years ago is a long way away from what it is today.

This is the all-important context for what I want to discuss about MDX because MDX is an offshoot of Markdown, only more capable of supporting richer forms of multimedia — and even user interaction. But before we get into that, we should also discuss the concept of web components because that’s the second significant piece that MDX brings to the table.

Further Reading

A Little About Components

The move towards richer multimedia websites and apps has led to a thriving ecosystem of web development frameworks and libraries, including React, Vue, Svelte, and Astro, to name a few. The idea that we can have reusable components that are not only interactive but also respond to each other has driven this growth and continues to push on evolving web platform features like web components.

MDX is like a bridge that connects Markdown with modern web tooling. Simply put, MDX weds Markdown’s simplicity with the creative possibilities of modern web frameworks.

By leaning into the overlaps rather than trying to abstract them away at all costs, we find untold potential for beautiful digital content.

Further Reading

A Case Study

My own experience with MDX took shape in a side project of mine: teeline.online. To cut a long story short, before I was a software engineer, I was a journalist, and part of my training involved learning a type of shorthand called Teeline. What it boils down to is ripping out as many superfluous letters as possible — I like to call this process “disemvowelment” — then using Teeline’s alphabet to write the remaining content. This has allowed people like me to write lots of words very quickly.

During my studies, I found online learning resources lacking, so as my engineering skills improved, I started working on the kind of site I’d have used when I was a student if it was available. Hence, teeline.online.

I built the teeling.online site with the Svelte framework for its components. The site’s centerpiece is a dataset of shorthand characters and combinations with which hundreds of outlines can be rendered, combined, and animated as SVG paths.

Likewise, Teeline’s “disemvowelment” script could be wired into a single component that I could then use as many times as I like.

Then, of course, as is only natural when working with components, I could combine them to show the Teeline evolution that converts longhand words into shorthand outlines.

The Markdown, meanwhile, looks as simple as this:

It’s not exactly the sort of complex codebase you might expect for an app. Meanwhile, the files themselves can sit in a nice, tidy directory of their own:

The syllabus is neatly filed away in its own folder. With a bit of metadata sprinkled in, I have everything I need to render an entire section of the site using routing. The setup feels like a fluid medium between worlds. If you want to write with words and pictures, you can. If an idea comes to mind for a component that would better express what you’re going for, you can go make it and drop it in.

In fairness, a “WordToOutline” component like this might not mean much to Teeline newcomers, though with such a clear connection between the Markdown and the rendered pages, it’s not much of a stretch to work out what it is. And, of course, there’s always the likes of services like Storybook that can be used to organize component libraries as they grow.

The raw form of multimedia content can be pretty unsightly — something that needs to be kept at arm’s length by content management systems. With MDX — and its ilk — the content feels rather friendly and legible.

Benefits

I think you can start to see some of the benefits of an MDX setup like this. There are two key benefits in particulart that I think are worth calling out.

Editorial Benefits

First and foremost, MDX doesn’t distract the writing and editorial flow of working with content. When we’re working with traditional code languages, even HTML, the code format is convoluted with things like opening and closing tags. And it’s even more convoluted if we need the added complexity of embedding components in the content.

MDX (and Markdown, for that matter) is much less verbose. Content is a first-class citizen that takes up way less space than typical markup, making it clear and legible. And where we need the complex affordance of components, those can be dropped in without disrupting that nice editorial experience.

Another key benefit of using MDX is reusability. If, for example, I want to display the same information as images instead, each image would have to be bespoke. But we all know how inefficient it is to maintain content in raster images — it requires making edits in a completely different application, which is highly inconvenient. With an old-school approach, if I update the design of the site, I’m left having to create dozens of images in the new style.

With MDX (or an equivalent like MDsveX), I only need to make the change once, and it updates everywhere. Having done the leg work of building reusable components, I can weave them throughout the syllabus as I see fit, safe in the knowledge that updates will roll out across the board — and do it without affecting the editorial experience whatsoever.

Consider the time it would take to create images or videos representing the same thing. Over time, using fixed assets like images becomes a form of technical — or perhaps editorial — debt that adds up over time, while a multimedia approach that leans into components proves to be faster and more flexible than vanilla methods.

Tech Benefits

I just made the point that working with reusable components in MDX allows Markdown content to become more robust without affecting the content’s legibility as we author it. Using Svelte’s version of MDX, MDsveX, I was able to combine the clean, readable conventions of Markdown with the rich, interactive potential of components.

Caveats

It’s only right that all my gushing about MDX and its benefits be tempered with a reality check or two. Like anything else, MDX has its limitations, and your mileage with it will vary.

That said, I believe that those limitations are likely to show up when MDX is perhaps not the best choice for a particular project. There’s a sweet spot that MDX fills and it’s when we need to sprinkle in additional web functionality to the content. We get the best of two worlds: minimal markup and modern web features.

But if components aren’t needed, MDX is overkill when all you need is a clean way to write content that ports nicely into HTML to be consumed by whatever app or platform you use to display it on the web.

Without components, MDX is akin to caring for a skinned elbow with a cast; it’s way more than what’s needed in that situation, and the returns you get from Markdown’s legibility will diminish.

Similarly, if your technical needs go beyond components, you may be looking at a more complex architecture than what MDX can support, and you would be best leaning into what works best for content in the particular framework or stack you’re using.

Code doesn’t age as well as words or images do. An MDX-esque approach does sign you up for the maintenance work of dependency updates, refactoring, and — god forbid — framework migrations. I haven’t had to face the last of those realities yet, though I’d say the first two are well worth it. Indeed, they’re good habits to keep.

Key Takeaways

Writing with MDX continues to be a learning experience for me, but it’s already made a positive impact on my editorial work.

Specifically, I’ve found that MEX improves the quality of my writing. I think more laterally about how to convey ideas.

Is what I’m saying best conveyed in words, an image, or a data visualization? Perhaps an interactive game?

There is way more potential to enhance my words with componentry than I would get with Markdown alone, opening more avenues for what I can say and how I say it.

Of course, those components do not come for free. MDX does sign you up to build those, regardless of whether you have a set of predefined components included in your framework. At the same time, I’d argue that the opportunities MDX opens up for writing greatly outweigh having to build or maintain a few components.

If MDX had been around in the age of Leonardo Di Vinci, perhaps he may have reached for MDX in his journals. I know I’m taking a great leap of assumption here, but the complexity of what he was writing and trying to describe in technical terms with illustrations would have benefited greatly from MDX for everything from interactive demos of his ideas to a better writing experience overall.

Further Reading

Multimedia Writing

In many respects, MDX’s rich, varied way of approaching content is something that Markdown — and writing for the web in general — encourages already. We don’t think only in terms of words but of links, images, and semantic structure. MDX and its equivalents merely take the lid off the cookie jar so we can enhance our work.

Wouldn’t it be nice if… is a redundant turn of phrase on the web. There may be technical hurdles — or, in my case, skill and knowledge hurdles — but it’s a buzz to think about ways in which your thoughts can best manifest on screen.

At the same time, the simplicity of Markdown is so unintrusive. If someone wants to write content formatted in vanilla Markdown, it’s totally possible to do that without trading up to MDX.

Just having the possibility of bespoke multimedia content is enough to change the creative process. It leaves you using words because you want to, not because you have to.

Why describe the solar system when you can render an explorable one? Why have a picture of a proposed skyscraper when you can display a 3D model? Writing with MDX (or, more accurately, MDsveX) has changed my entire thought process. Potential answers to the question, How do I best get this across?, become more expansive.

As You Please

Good things happen when worlds collide. New possibilities emerge when seemingly disparate things come together. Many content management systems shield writers — and writing — from code. To my mind, this is like shielding painters from wider color palettes, chefs from exotic ingredients, or sculptors from different types of tools.

Leaning into the overlap between writing and coding gets us closer to one of the web’s great joys: if you can imagine it, you can probably do it.