WordPress Community Team Proposes Stricter COVID-19 Safety Protocols for In-Person Events in 2022

Mounting concerns about loose safety protocols at upcoming WordPress events, and the prevalence of the highly transmissible Omicron variant, have prompted the Community Team to be more explicit in its COVID-19 safety guidelines. The team is proposing additional measures previously not required.

Currently, in-person attendees are required to be fully vaccinated, recently tested negative, or recently recovered from COVID-19. Every one of these requirements is vague and open to multiple interpretations. Recent spikes in infection in both vaccinated and unvaccinated populations has caused the Community Team to propose the following:

  • Mandatory masks for all attendees (even in regions that do not have a mask mandate at this time). 
  • More prominent messaging in WordCamp websites, emails, and social media posts about COVID-19 safety guidelines.
  • Mandatory temperature checks for all attendees at the event (if permitted by local authorities).
  • Accessible hand sanitizing stations in the venue.
  • Maintaining social distancing practices during the event (Larger meeting rooms and seating arrangements with good spacing can be a good way to implement this).
  • Having a plan for contact tracing measures in case of infections (can be done using WordCamp registration data, meetups are a bit tricker).

One of the concerns with imposing more mandatory safety measures is enforcement. WordPress events are generally hosted by volunteers who would now need to go beyond simply facilitating an event to being ready to confront and remove those who don’t comply with safety protocols. In a community of people with diverse convictions, what happens if some members decide that WordCamp is a good place to protest pandemic restrictions?

“I appreciate very much the heart behind wanting to keep the community safe, but have significant issue with how this is being proposed, and how it would be enforced, and how it shifts the burden of health and safety to a volunteer team of organizers who are not in any way trained or equipped to handle making medical decisions,” Ben Meredith said.

“Further, there are many jurisdictions where the proposed changes (like a mask mandate) are specifically prohibited by local law or executive order.

“Trying to make a policy from the international level (WordCamp central) that applies fairly and equitably to all local jurisdictions is a fool’s errand. What works in Los Angeles probably wont in Louisiana or Lagos. That’s why organizers are local.”

If the WordPress community is fixed on hosting events at this time, then there are many more responsibilities organizers are now obligated to assume in order to ensure the safety of attendees. Participants in the discussion on the proposal raised dozens of questions about how these new safety measures might be implemented.

“On temp checks, if someone reads high ( they may not even be aware) would we then refund their ticket to the event assuming we are talking a WordCamp?” Laura Byrne asked.

 WordCamp organizer and speaker David Ryan raised questions about masks, will the requirements outline what qualifies as a mask? (“Does a plastic face shield qualify as a mask? Are masks with ventilation valves acceptable? A bandana?”) Does the requirement include speakers while they are speaking? “This should be clear in advance for both speakers and attendees to make informed choices without surprises day-of,” Ryan said.

He also asked if the masking policies extend to other venues, such as the official event hotel and after parties, the way the Code of Conduct applies.

Refunds are another consideration. Will WordCamps refund people who test positive right before the event? Will the event refund if people arrive and are not comfortable or are asked to leave for not complying with the safety measures?

“In addition to these proposed guidelines, I also recommend that we remove our existing guideline of allowing recent-recovered community members from attending a WordPress event since new COVID variants like Omicron are known to cause reinfection,” Automattic-sponsored WordPress Community Wrangler Hari Shanker said in the proposal.

Laura Byrne urged the Community Team to clearly define this guideline.

“We are in for a boatload of trouble with the word ‘recent,'” Byrn said. “In other words, something along the lines of, ‘anyone who has tested positive for COVID may not attend a WordPress event until X days after they are no longer testing positive.'”

Some participants in the discussion see the additional safety measures as an overreach for WordPress events. It’s easier and more straightforward to recommend organizers stick with local requirements for anything related to health safety.

“Surely I’m not the only one thinking that the foundation shouldn’t be setting health guidelines at all?” Cameron Jones said. “Compliance with local regulations should be the only requirement.”

The problem with this is that many locations and regions do not have any kind of precautions in place, due to political differences, or are slow in recognizing emerging threats. Lax local guidelines for large gatherings may leave the WordPress community vulnerable to outbreaks.

“As a WordCamp organizer and speaker, and more personally as a recent cancer survivor and immunocompromised person, State of the Word was a troubling event to observe,” David Ryan said.

“Local legal requirements were met, but not proven event practices that eliminated or greatly-reduced positivity rate at larger gatherings in 2021 compared to the results of SOTW (namely, masks and testing). Planning, day-of and response afterwards didn’t inspire confidence this community was prepared to run safer and inclusive events — so this is an encouraging step towards remedying concerns many have expressed.”

Comments on the proposal are open until January 22, 2022. The Community team plans to assess the feedback and finalize the updated guidelines in time to publish them to the handbook in early February 2022.

How to show/hide divs with links when $_SESSION variable for cart exists

Trying to show divs and elements when a session doesn't exist. But when I save an item to a cart/wish-list a session starts and goes back to a page that is now supposed to show the item info and hide <td id="cartHideBtn">...</td>.

//shows when no session exists, but also needs to show again if user removes item from cart/wish-list, or show when another part is added 
//in a different category
<td id="cartHideBtn" class="add-component">
    <a href="content.php?PartType=UpperReceiver" class="add-btn"><i class="fas fa-plus"></i>ADD</a>
</td>

If session exists and a product is added then display this.

<?php
    if (isset($_SESSION['buildList'])) {
        foreach ($_SESSION['buildList'] as $product) :
            if ($product['PartType'] == 'UPPER RECEIVER') {
?>

<tr>
    <td>
        <a href="pageContent.php?id=<?php echo $product['id'];?>"><img class="p-img" src="<?php echo $product['Image_thumb'];?>"/></a>
    </td>
    <td>
        <h6>MANUFACTURER</h6>
            <p>
                <?php
                    echo $product["Manufacturer"];
                ?>
            </p>
    </td>
    <td>
        <p><?php echo $product["Price"];?></p>
    </td>
</tr>

//this is button to remove item.
<td class="td-remove">
    <form method="get" action="./controllers/WishBuild.php" class="fm-remove">
        <input type="hidden" name="type" value="remove">
        <input type="hidden" name="id" value="<?php echo $product['id'];?>">
        <button type="submit" name="removed" class="rem-btn"><i class="fas fa-minus"></i>REMOVE</button>
     </form>
</td>                  

<?php
            }
        endforeach;
    } 
?>

I have several categories, titled Part1, Part2, Part3...etc. So the above code is for one category. Basically, part1 takes you to part1 products and so on, if product in part1 is added then display it in part1 then user goes onto adding part2...etc. So far the above code works I can add the products and they show where they need to be but the "add" links still show and want them to be hidden. Trying to figure out best way to do this and how. Thanks for any input.

countdown with 3 label, (hh:mm:ss) when reach 1 minute timer freeze

Hi, I have a issues, in this code I have a countdown with function declared, the issues now is that, if starting the time with only seconds timer go well but if the timer go to one minute if button is clicked timer suddently stop. Is there anything wrong with the code?

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        If Label5.Text = 0 AndAlso Label8.Text = 0 AndAlso Label7.Text < 59 Then
            Label7.Text = Label7.Text - 1.ToString
            If Label5.Text = 0 AndAlso Label8.Text = 0 AndAlso Label7.Text = 0 Then
                Timer1.Stop()
                MsgBox("timer out", MessageBoxButtons.OK)
            End If
            If Label7.Text = 0 AndAlso Label8.Text > 1 Then
                Label8.Text = Label8.Text - 1.ToString
                Label7.Text = 59
            ElseIf Label5.Text >= 0 AndAlso Label8.Text >= 0 AndAlso Label7.Text = 59 Then
                Label7.Text = 59
                Label8.Text = 59
                Label7.Text = Label7.Text - 1.ToString
                Label8.Text = Label8.Text - 1.ToString
                Label5.Text = Label5.Text - 1.ToString
            End If
        End If
    End Sub

Customizer Will Disappear for Some Block Theme Users With WordPress 5.9

Nine years ago, the customizer had a rocky start among theme authors and users. Despite this, it has become the standard for modifying the look and feel of a website. Developers have become comfortable with the API. Users have grown accustomed to adjusting colors, fonts, and even internal WordPress options through it. However, it will disappear for many once a block theme is activated.

I began writing this post on the upcoming block-based theme system and site editor. However, I spent so much time explaining the customizer changes that I thought it best to focus on that aspect to let users know their options if they run into a snag.

It is also a follow-up to a post I published in October 2021 on the same subject. Since then, some things have changed.

WordPress 5.9 will launch with several of the final components of Full Site Editing. The centerpiece of these features will be a new theme system, which allows themers to build designs entirely out of blocks. Once such a theme is active, users can edit their site’s front end via the site editor and global styles system.

The site editor is, essentially, the next iteration of what the customizer aimed to do. The difference is that users can now customize every aspect of their site’s front-end and not just configure the options their theme author made available.

For many block theme users, the disappearance of the customizer will be a non-issue. However, three missing options have no exact equivalent:

  • A partial site icon (favicon) solution exists but not for every scenario.
  • The custom CSS box is not available.
  • There is no draft process before switching to block theme.

Technically, the customizer is available via /wp-admin/customize.php. Even though no links to it are shown in the admin, any user with the requisite permissions can access it via that URL. At the very least, the first two issues can be mitigated by editing options in this way. It is not ideal, but it will work in a pinch.

The Site Logo block has a “use as site icon” option. This is a quick and easy way to update the logo and favicon via the new site editor, assuming they use the same image.

Site Logo block selected in the site editor.  On the right, the Settings panel is open, showing an option for using the logo as a site icon.
New “Use as site icon” option.

If they are different images or if the user does not use a logo, the only built-in way to change the site icon directly is through the customize.php URL trick mentioned above. The Site Logo block also adds a link to the customizer option. Users can also opt for one of the dozens of favicon plugins.

A custom CSS solution in core WordPress is unlikely to be reimplemented in the site editor. The global styles panel and per-block design options are the future of styling. This makes many of the most common stylistic tasks much easier for non-coders. In the context of block-based themes, the average user is unlikely to need the CSS editor in the customizer.

WordPress customizer open.  The panel on the left shows the Additional CSS section with some custom code.
Custom CSS section in the customizer.

However, there are situations where custom CSS is necessary. Again, the easy answer is to access customize.php once again. For a more dedicated solution, there are numerous plugins available.

There is currently no solution for live previewing and customizing inactive block themes. With classic ones, users can test customizations before activation. In the customizer, block themes will appear with a warning message.

Theme details popup in the customizer when viewing a theme.  It has a message that it doesn't support the customizer before its description and tags.  On the left is the theme screenshot.
Theme details with warning about customizer support.

Once a block theme is activated from the customizer, WordPress will return the user to the Appearance > Themes page in the admin. They can then modify their site via the site editor.

However, this can be problematic for some sites. Just about any theme change will mean there is at least some customization work in order, and most people will not want their visitors to see an unfinished site. Working from a dev or staging site before migrating the changes is ideal. However, that option is not always available or even easy to figure out for everyone.

Another solution is to install a maintenance-mode plugin if working on a live site. This way, visitors will at least know some changes are happening under the hood and that they can return later.

There is an open ticket for previewing and editing inactive block themes. As ticket creator Anton Vlasenko wrote as the proposed solution, “It’s simple: we need to implement that feature.” In the long term, this is a must-have feature.

There is one situation where the customizer will still be accessible via the admin menu and toolbar. WordPress will automatically detect when a plugin or theme hooks into the customizer and make links to it available. I like to think that my first post covering block themes and the customizer raised awareness of this issue. At the very least, we now have a fix in place.

Assuming there are no other changes in the next two weeks, this is how the customizer will function when paired with an active block theme.

Best Watercolor Paper Reviews

Choosing the best watercolour paper is critical when you are experimenting with painting. The ideal water colour paper able to handle moist substances and offers multiple vibrant colors. Papers are normally substantial, weighing roughly within 300gsm/140lbs, however, the student pages are thin. A plenty of water reduces colour materials, particularly ones that are just too...

The post Best Watercolor Paper Reviews appeared first on DesignrFix.

How To Use Sticker Paper

Sticker papers are getting several uses from time to time in the current world. Traditionally, people used to get sticker papers from the shops and stores where they came with already made appearances. Today, due to technological advancement, you can create customized sticker paper for your use. Sticker papers come in various forms to meet...

The post How To Use Sticker Paper appeared first on DesignrFix.

How to Print on Transparencies

Transparencies are a popular way to present information through slideshows. They have long been used in classrooms and lecture halls, but they’re also starting to pop up at the office as an alternative to overhead projectors or flip charts. Printing on transparency papers gives you more options than plain paper for presenting your ideas graphically....

The post How to Print on Transparencies appeared first on DesignrFix.

A Stress-Free 2022

There are ample resources available online to deal with burnout in your job, but I want to share a few ideas that I will be using this year. The WHO says: “Burn-out is a syndrome conceptualized as resulting from chronic workplace stress that has not been successfully managed.” You know that it is happening to you when a part of your inner self is screaming that you have had enough. Perhaps, you want to say it out loud, too. IT jobs seem to have a high percentage of burnout, and Electric identifies that it is rising.

January is the month when employees return from a festive break to start afresh and tackle new challenges. However, IT professionals return to the unfinished backlog, pushed deadlines, and overcommitted sprints from December. Long hours, growing to-do lists, work setup issues, uncountable Slack messages, and remote teams all contribute to stress. We all face it. Long hours and working over the weekends contribute to the biggest reasons for burnout. Teams work throughout the week, release during the nights, and provide support over the weekends, and the cycle continues.

How To Detect and Secure Your Java App From Log4j Vulnerabilities

Apache Log4j is the popular open source logging library for Java developers that was recently caught up in a massive security-related breach. Due to its popularity, a large number of organizations were affected by the breach. For the latest news, refer to the official website about specific issues and patches. Here is an additional article that explains the core issues in detail.

List of Security Issues That Were Found in Log4j Version 2.x:

  1. CVE-2017-5645: Apache Log4j socket receiver deserialization vulnerability  (Severity - Moderate)
  2. CVE-2020-9488: Improper validation of certificate with host mismatch in Apache Log4j SMTP appender (Severity - Low)
  3. CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker-controlled LDAP and other JNDI-related endpoints (Severity - Critical)
  4. CVE-2021-45046: Apache Log4j2 Thread Context Lookup Pattern vulnerable to remote code execution in certain non-default configurations (Severity - Critical)
  5. CVE-2021-45105: Apache Log4j2 does not always protect from infinite recursion in lookup evaluation (Severity - Critical)
  6. CVE-2021-44832: Apache Log4j2 vulnerable to RCE via JDBC Appender when attacker controls configuration (Severity - Moderate)

4 Ways To Secure Your Java Application:

1.  Detect if You Have Log4j 2.x in Your Code Base 

Apache Log4j can be in your project directly or a dependency of a dependency. Thus, it's best to use a build tool such as Maven or Gradle to quickly scan for the same tree as follows:

How To Build Self-Hosted RSS Feed Reader Using Spring Boot and Redis

Keeping on top of your RSS feeds can be a headache. If you have many feeds that you follow, then trying to keep tabs on the status of each one is just as tedious as difficult. Let’s be honest: having to dig through the online clutter and pull out the feed you want to monitor is a time-consuming process that nobody wants to experience.

These inconveniences created an itch that Sandeep Gupta couldn’t ignore, which spurred him to create an application that pulls all RSS feeds into one location. This provides users with a holistic view of all their RSS feeds, promoting a painless and efficient way of organizing their entire collection. Using different Redis modules, Sandeep was able to create an application that’s hyper-responsive to user commands, minimizing the chances of any lags or delays from happening. 

What Log4j Vulnerability Means for SREs

If you’re an SRE, you’ve almost certainly heard all about Log4Shell, the Log4j vulnerability that some analysts are calling the worst software security flaw in decades. And you’ve also hopefully by now patched any systems you manage to fix the vulnerability (if you haven’t, go do that right away!).

Even after you’ve patched Log4Shell in your environments, though, you shouldn’t put the vulnerability in the back of your mind. For SREs, there are some important lessons to glean from this fiasco.

Don’t Fight the Cascade, Control It!

If you’re disciplined and make use of the inheritance that the CSS cascade provides, you’ll end up writing less CSS. But because our styles often comes from all kinds of sources — and can be a pain to structure and maintain—the cascade can be a source of frustration, and the reason we end up with more CSS than necessary.

Some years ago, Harry Roberts came up with ITCSS and it’s a clever way of structuring CSS.

Mixed with BEM, ITCSS has become a popular way that people write and organize CSS.

However, even with ITCSS and BEM, there are still times where we still struggle with the cascade. For example, I’m sure you’ve had to @import external CSS components at a specific location to prevent breaking things, or reach for the dreaded !important at some point in time.

Recently, some new tools were added to our CSS toolbox, and they allow us to finally control the cascade. Let’s look at them.

O cascade, :where art thou?

Using the :where pseudo-selector allows us to remove specificity to “just after the user-agent default styles,” no matter where or when the CSS is loaded into the document. That means the specificity of the whole thing is literally zero — totally wiped out. This is handy for generic components, which we’ll look into in a moment.

First, imagine some generic <table> styles, using :where:

:where(table) {
  background-color: tan;
}

Now, if you add some other table styles before the :where selector, like this:

table {
  background-color: hotpink;
}

:where(table) {
  background-color: tan;
}

…the table background becomes hotpink, even though the table selector is specified before the :where selector in the cascade. That’s the beauty of :where, and why it’s already being used for CSS resets.

:where has a sibling, which has almost the exact opposite effect: the :is selector.

The specificity of the :is() pseudo-class is replaced by the specificity of its most specific argument. Thus, a selector written with :is() does not necessarily have equivalent specificity to the equivalent selector written without :is(). Selectors Level 4 specification

Expanding on our previous example:

:is(table) {
  --tbl-bgc: orange;
}
table {
  --tbl-bgc: tan;
}
:where(table) {
  --tbl-bgc: hotpink;
  background-color: var(--tbl-bgc);
}

The <table class="c-tbl"> background color will be tan because the specificity of :is is less specific than table.

However, if we were to change it to this:

:is(table, .c-tbl) {
  --tbl-bgc: orange;
}

…the background color will be orange, since :is has the weight of it’s heaviest selector, which is .c-tbl.

Example: A configurable table component

Now, let’s see how we can use :where in our components. We’ll be building a table component, starting with the HTML:

Let’s wrap .c-tbl in a :where-selector and, just for fun, add rounded corners to the table. That means we need border-collapse: separate, as we can’t use border-radius on table cells when the table is using border-collapse: collapse:

:where(.c-tbl) {
  border-collapse: separate;
  border-spacing: 0;
  table-layout: auto;
  width: 99.9%;
}

The cells use different styling for the <thead> and <tbody>-cells:

:where(.c-tbl thead th) {
  background-color: hsl(200, 60%, 40%);
  border-style: solid;
  border-block-start-width: 0;
  border-inline-end-width: 1px;
  border-block-end-width: 0;
  border-inline-start-width: 0;
  color: hsl(200, 60%, 99%);
  padding-block: 1.25ch;
  padding-inline: 2ch;
  text-transform: uppercase;
}
:where(.c-tbl tbody td) {
  background-color: #FFF;
  border-color: hsl(200, 60%, 80%);
  border-style: solid;
  border-block-start-width: 0;
  border-inline-end-width: 1px;
  border-block-end-width: 1px;
  border-inline-start-width: 0;
  padding-block: 1.25ch;
  padding-inline: 2ch;
}

And, because of our rounded corners and the missing border-collapse: collapse, we need to add some extra styles, specifically for the table borders and a hover state on the cells:

:where(.c-tbl tr td:first-of-type) {
  border-inline-start-width: 1px;
}
:where(.c-tbl tr th:last-of-type) {
  border-inline-color: hsl(200, 60%, 40%);
}
:where(.c-tbl tr th:first-of-type) {
  border-inline-start-color: hsl(200, 60%, 40%);
}
:where(.c-tbl thead th:first-of-type) {
  border-start-start-radius: 0.5rem;
}
:where(.c-tbl thead th:last-of-type) {
  border-start-end-radius: 0.5rem;
}
:where(.c-tbl tbody tr:last-of-type td:first-of-type) {
  border-end-start-radius: 0.5rem;
}
:where(.c-tbl tr:last-of-type td:last-of-type) {
  border-end-end-radius: 0.5rem;
}
/* hover */
@media (hover: hover) {
  :where(.c-tbl) tr:hover td {
    background-color: hsl(200, 60%, 95%);
  }
}

Now we can create variations of our table component by injecting other styles before or after our generic styles (courtesy of the specificity-stripping powers of :where), either by overwriting the .c-tbl element or by adding a BEM-style modifier-class (e.g. c-tbl--purple):

<table class="c-tbl c-tbl--purple">
.c-tbl--purple th {
  background-color: hsl(330, 50%, 40%)
}
.c-tbl--purple td {
  border-color: hsl(330, 40%, 80%);
}
.c-tbl--purple tr th:last-of-type {
  border-inline-color: hsl(330, 50%, 40%);
}
.c-tbl--purple tr th:first-of-type {
  border-inline-start-color: hsl(330, 50%, 40%);
}

Cool! But notice how we keep repeating colors? And what if we want to change the border-radius or the border-width? That would end up with a lot of repeated CSS.

Let’s move all of these to CSS custom properties and, while we’re at it, we can move all configurable properties to the top of the component’s “scope“ — which is the table element itself — so we can easily play around with them later.

CSS Custom Properties

I’m going to switch things up in the HTML and use a data-component attribute on the table element that can be targeted for styling.

<table data-component="table" id="table">

That data-component will hold the generic styles that we can use on any instance of the component, i.e. the styles the table needs no matter what color variation we apply. The styles for a specific table component instance will be contained in a regular class, using custom properties from the generic component.

[data-component="table"] {
  /* Styles needed for all table variations */
}
.c-tbl--purple {
  /* Styles for the purple variation */
}

If we place all the generic styles in a data-attribute, we can use whatever naming convention we want. This way, we don’t have to worry if your boss insists on naming the table’s classes something like .BIGCORP__TABLE, .table-component or something else.

In the generic component, each CSS property points to a custom property. Properties, that have to work on child-elements, like border-color, are specified at the root of the generic component:

:where([data-component="table"]) {
  /* These will will be used multiple times, and in other selectors */
  --tbl-hue: 200;
  --tbl-sat: 50%;
  --tbl-bdc: hsl(var(--tbl-hue), var(--tbl-sat), 80%);
}

/* Here, it's used on a child-node: */
:where([data-component="table"] td) {
  border-color: var(--tbl-bdc);
}

For other properties, decide whether it should have a static value, or be configurable with its own custom property. If you’re using custom properties, remember to define a default value that the table can fall back to in the event that a variation class is missing.

:where([data-component="table"]) {
  /* These are optional, with fallbacks */
  background-color: var(--tbl-bgc, transparent);
  border-collapse: var(--tbl-bdcl, separate);
}

If you’re wondering how I’m naming the custom properties, I’m using a component-prefix (e.g. --tbl) followed by an Emmett-abbreviation (e.g. -bgc). In this case, --tbl is the component-prefix, -bgc is the background color, and -bdcl is the border collapse. So, for example, --tbl-bgc is the table component’s background color. I only use this naming convention when working with component properties, as opposed to global properties which I tend to keep more general.

Now, if we open up DevTools, we can play around with the custom properties. For example, We can change --tbl-hue to a different hue value in the HSL color, set --tbl-bdrs: 0 to remove border-radius, and so on.

A :where CSS rule set showing the custom properties of the table showing how the cascade’s specificity scan be used in context.

When working with your own components, this is the point in time you’ll discover which parameters (i.e. the custom property values) the component needs to make things look just right.

We can also use custom properties to control column alignment and width:

:where[data-component="table"] tr > *:nth-of-type(1)) {
  text-align: var(--ca1, initial);
  width: var(--cw1, initial);
  /* repeat for column 2 and 3, or use a SCSS-loop ... */
}

In DevTools, select the table and add these to the element.styles selector:

element.style {
  --ca2: center; /* Align second column center */
  --ca3: right; /* Align third column right */
}

Now, let’s create our specific component styles, using a regular class, .c-tbl (which stands for “component-table” in BEM parlance). Let’s toss that class in the table markup.

<table class="c-tbl" data-component="table" id="table">

Now, let’s change the --tbl-hue value in the CSS just to see how this works before we start messing around with all of the property values:

.c-tbl {
  --tbl-hue: 330;
}

Notice, that we only need to update properties rather than writing entirely new CSS! Changing one little property updates the table’s color — no new classes or overriding properties lower in the cascade.

Notice how the border colors change as well. That’s because all the colors in the table inherit from the --tbl-hue variable

We can write a more complex selector, but still update a single property, to get something like zebra-striping:

.c-tbl tr:nth-child(even) td {
  --tbl-td-bgc: hsl(var(--tbl-hue), var(--tbl-sat), 95%);
}

And remember: It doesn’t matter where you load the class. Because our generic styles are using :where, the specificity is wiped out, and any custom styles for a specific variation will be applied no matter where they are used. That’s the beauty of using :where to take control of the cascade!

And best of all, we can create all kinds of table components from the generic styles with a few lines of CSS.

Purple table with zebra-striped columns
Light table with a “noinlineborder” parameter… which we’ll cover next

Adding parameters with another data-attribute

So far, so good! The generic table component is very simple. But what if it requires something more akin to real parameters? Perhaps for things like:

  • zebra-striped rows and columns
  • a sticky header and sticky column
  • hover-state options, such as hover row, hover cell, hover column

We could simply add BEM-style modifier classes, but we can actually accomplish it more efficiently by adding another data-attribute to the mix. Perhaps a data-param that holds the parameters like this:

<table data-component="table" data-param="zebrarow stickyrow">

Then, in our CSS, we can use an attribute-selector to match a whole word in a list of parameters. For example, zebra-striped rows:

[data-component="table"][data-param~="zebrarow"] tr:nth-child(even) td {
  --tbl-td-bgc: var(--tbl-zebra-bgc);
}

Or zebra-striping columns:

[data-component="table"][data-param~="zebracol"] td:nth-of-type(odd) {
  --tbl-td-bgc: var(--tbl-zebra-bgc);
}

Let’s go nuts and make both the table header and the first column sticky:


[data-component="table"][data-param~="stickycol"] thead tr th:first-child,[data-component="table"][data-param~="stickycol"] tbody tr td:first-child {
  --tbl-td-bgc: var(--tbl-zebra-bgc);
  inset-inline-start: 0;
  position: sticky;
}
[data-component="table"][data-param~="stickyrow"] thead th {
  inset-block-start: -1px;
  position: sticky;
}

Here’s a demo that allows you to change one parameter at a time:

The default light theme in the demo is this:

.c-tbl--light {
  --tbl-bdrs: 0;
  --tbl-sat: 15%;
  --tbl-th-bgc: #eee;
  --tbl-th-bdc: #eee;
  --tbl-th-c: #555;
  --tbl-th-tt: normal;
}

…where data-param is set to noinlineborder which corresponds to these styles:

[data-param~="noinlineborder"] thead tr > th {
  border-block-start-width: 0;
  border-inline-end-width: 0;
  border-block-end-width: var(--tbl-bdw);
  border-inline-start-width: 0;
}

I know my data-attribute way of styling and configuring generic components is very opinionated. That’s just how I roll, so please feel free to stick with whatever method you’re most comfortable working with, whether it’s a BEM modifier class or something else.

The bottom line is this: embrace :where and :is and the cascade-controlling powers they provide. And, if possible, construct the CSS in such a way that you wind up writing as little new CSS as possible when creating new component variations!

Cascade Layers

The last cascade-busting tool I want to look at is “Cascade Layers.” At the time of this writing, it’s an experimental feature defined in the CSS Cascading and Inheritance Level 5 specification that you can access in Safari or Chrome by enabling the #enable-cascade-layers flag.

Bramus Van Damme sums up the concept nicely:

The true power of Cascade Layers comes from its unique position in the Cascade: before Selector Specificity and Order Of Appearance. Because of that we don’t need to worry about the Selector Specificity of the CSS that is used in other Layers, nor about the order in which we load CSS into these Layers — something that will come in very handy for larger teams or when loading in third-party CSS.

Perhaps even nicer is his illustration showing where Cascade Layers fall in the cascade:

Credit: Bramus Van Damme

At the beginning of this article, I mentioned ITCSS — a way of taming the cascade by specifying the load-order of generic styles, components etc. Cascade Layers allow us to inject a stylesheet at a given location. So a simplified version of this structure in Cascade Layers looks like this:

@layer generic, components;

With this single line, we’ve decided the order of our layers. First come the generic styles, followed by the component-specific ones.

Let’s pretend that we’re loading our generic styles somewhere much later than our component styles:

@layer components {
  body {
    background-color: lightseagreen;
  }
}

/* MUCH, much later... */

@layer generic { 
  body {
    background-color: tomato;
  }
}

The background-color will be lightseagreen because our component styles layer is set after the generic styles layer. So, the styles in the components layer “win” even if they are written before the generic layer styles.

Again, just another tool for controlling how the CSS cascade applies styles, allowing us more flexibility to organize things logically rather than wrestling with specificity.

Now you’re in control!

The whole point here is that the CSS cascade is becoming a lot easier to wrangle, thanks to new features. We saw how the :where and :is pseudo-selectors allows us to control specificity, either by stripping out the specificity of an entire ruleset or taking on the specificity of the most specific argument, respectively. Then we used CSS Custom Properties to override styles without writing a new class to override another. From there, we took a slight detour down data-attribute lane to help us add more flexibility to create component variations merely by adding arguments to the HTML. And, finally, we poked at Cascade Layers which should prove handy for specifying the loading order or styles using @layer.

If you leave with only one takeaway from this article, I hope it’s that the CSS cascade is no longer the enemy it’s often made to be. We are gaining the tools to stop fighting it and start leaning into even more.


Header photo by Stephen Leonardi on Unsplash


Don’t Fight the Cascade, Control It! originally published on CSS-Tricks. You should get the newsletter and become a supporter.

Let the Oracle Database Operator for Kubernetes Do the Job

Hello everyone! New Year, New Life, and finally, old dreams and goals are coming out of the paper. For my first blog, at the beginning of 2022, I chose to talk about Oracle Database Kubernetes Operator, a.k.a OraOperator. 

In this post, I'll talk about Oracle Database Kubernetes Operator, a.k.a OraOperator, and offer a gentle introduction to Kubernetes Operator and Cloud-Native Architecture -- base for all.

Penetration Testing 101: A Beginner’s Guide to Ethical Hacking

Every day, we use and generate huge amounts of data. And this data is used by different sectors like healthcare, finance, marketing, and others. However, data breaches are increasingly rampant these days. That’s why such sensitive information should be safeguarded.

This is where penetration hacking comes in handy. Penetration testing or ethical hacking is used to get access to resources. Hackers carry out attacks to uncover security vulnerabilities and assess their strengths.

How To Use NUnit Annotations For Selenium Automation Testing [With Example]

When it comes to using object-oriented programming languages for development & testing, C# is still considered a good choice by the developer community. MSTest/Visual Studio, xUnit.net, and NUnit are some of the top-most frameworks that can be used for automated browser testing. While using NUnit, you can further leverage the capabilities of NUnit Annotations to build a more robust framework.

Any discussion about testing is incomplete without the mention of the Selenium framework. Selenium is a powerful test framework that can be used for automated browser testing as it is compatible with popular programming languages like C#, Python, etc.