Styling

jwp

John Peters

Posted on December 31, 2022

Styling

In the previous article we introduced the Display-Grid Web Component which supports markup like this:

<display-grid>  
    <grid-col>Column A
        <p>Lorem ipsum...</p>
        <a href="SomeURL">Go Here</a>
    </grid-col>     
    <grid-col>Column B
        <p>Lorem ipsum...<p>
    </grid-col>
    <grid-col>Column C
        <p>Lorem ipsum...</p>
        <p>Lorem ipsum ...</p>
    </grid-col>     
</display-grid>
Enter fullscreen mode Exit fullscreen mode

Automatic Styling

The idea is to allow for automatic CSS Grid markup; which looks like this, for three columns.

CSS for a grid with 3 columns

The number of columns are based on the number of <grid-col> subelements.

In the original article there was a bug related to the shadow root.

We Found a Bug

Not having a full understanding of
const shadowRoot = this.attachShadow({mode:"open"});

We created the shadowRoot the parent (display-grid) and one for each sub-element (grid-col).

The impact of this was indeterminate view rendering; which, was highly dependent on element and child element placement!

The fix was to not open up any shadowRoots!

The Fix

We wanted the parent (display-grid) to set all styling for itself and all it's (grid-col) children.

In the master (display-grid) element, we removed the shadowRoot code like this:

customElements.define(
  "display-grid",
  class extends HTMLElement {
    constructor() {
      super();
      //const shadowRoot = this.attachShadow({mode: 'open'});
      this.SetStyleByColumns();
    }

Enter fullscreen mode Exit fullscreen mode

SetStyleByColumns

Then we altered this styling for this (parent) element and all the (grid-col) elements.

/**Based on the number of grid-col elements set up the grid column count to match */
SetStyleByColumns() {
  //grid-col is a custom element
  let cols = document.querySelectorAll("grid-col");
  // numberOfColumns returns something like "auto auto auto" for 3 columns
  const textContent = this.getStyleByCols(cols);
  this.style= document.createElement("style").textContent=textContent;
  for (let col of cols) {
    col.style = document.createElement("style").textContent = "padding:2rem;";

  }
}
getStyleByCols(cols) {
  var numberOfColumns = this.GetNumberOfGridColumnsToAdd(cols);
  var style = `background-color:#444;
    color:white;
    display:grid; 
    grid-template-columns:${numberOfColumns};
  `;
  return style;
}

GetNumberOfGridColumnsToAdd(cols) {
  var AutoCount;
  cols.forEach((item) => {
    if (AutoCount == undefined) {
      AutoCount = "auto ";
      return;
    }
    AutoCount += "auto ";
  });
  return AutoCount;
}
Enter fullscreen mode Exit fullscreen mode

The result of the code above for the Display-Grid element:

Image description

And for each (grid-col) element:

grid-col css

The HTML Result

The HTML Result

The Rendering

The Rendering of the Three Column Grid

This taught us that we don't have a good understanding of how the shadowroot works. For now we don't need it and will study it later.

Other Information

This design is ok but not great. Due to specificity rules; by placing the styling at the element layer, there is nothing the user can do to override this except perhaps using the (forbidden?) !important keyword.

We could add a class style and test in lab to see if this opens a path for better user control.

No Binding

Another unforeseen issue in this design, is that it does not separate the data from the GUI, this means that something simple like sorting data (not needed for this example) is impossible. This current design re-renders all of the markup each time this page is reloaded.

In order for these components to be reusable, there must be considerations for easily styling this component for any situation. After all, Web Components are meant to be reused.

💖 💪 🙅 🚩
jwp
John Peters

Posted on December 31, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related