Pull to refresh

Web Content Elements

Level of difficultyMedium
Reading time7 min
Views1K

In HTML we use tag as a discriminator between elements. Every HTML tag stands for different element. We use classes to apply styles to the elements. We provide custom solutions to build and maintain the architecture of the structure and style system and interaction of both.

Web Content Elements stands for a concept, a design pattern to bring these kind of solutions to a single and linear approach. It is applied to handle a daily web development routine(generating of HTML and CSS).

In terms of Web Content Development HTML tag is just a variable(an argument) that is used to generate the element.

The main idea is to use the element’s role as a discriminator, as the main reference for the entity.

💡 Elements are grouped by the role they represent in the content of the page.

Base roles are:

  • Block

  • Text

  • Image

  • Link

  • Button

  • Divider

  • List

Other roles that handle utility functions or serve as helpers for developers are:

  • Custom
    Provide custom structures within the Web Content Elements approach

React Content Elements is a library that implements the WCE pattern within React and Typescript.

Official webpage

NPM package

Github

Basics

Content Elements are named by their role.

A simple example will work best:

import CE from 'react-content-elements';
 
<CE.Block>Block Content Element</CE.Block>
// HTML
<div class="ce ce-block">Block Content Element</div>
 
<CE.Text>Text Content Element</CE.Text>
// HTML
<p class="ce ce-text">Text Content Element</p>
 
<CE.Image src="link/to/the-image.jpg" />
// HTML
<img class="ce ce-image" src="link/to/the-image.jpg" />
 
<CE.Link>Link Content Element</CE.Link>
// HTML
<a class="ce ce-link">Link Content Element</a>
 
<CE.Button>Button Content Element</CE.Button>
// HTML
<button class="ce ce-link" type="button">Button Content Element</button>
 
<CE.Divider />
// HTML
<hr class="ce ce-divider" />

Now let’s analyse the process deeply.

Every Content Element has:

  • default tag 
    It’s applied by the name of the element. ‘p’ for the Text Content Element

  • base class: ce ce-[name] 
    f.e. “ce ce-text” for the Text Content Element

Now, as we have learned basics of structure generating let’s switch to the styles.

As it’s been mentioned every Content Element has a base class that might be referred to in your CSS.

Though it’s pretty straightforward how to apply the styles to your HTML, Web Content Elements brings you even more handy solution to organize the style system.

Take a look at the SASS mixins presented below.

@use 'react-content-element/styles/utils' as *;

/* by content element */
@include byName {
  color: red;
}
// CSS
.ce {
  color: red;
}

/* by content element name */
@include byName('text') {
  font-size: 16px;
}
// CSS
.ce-text {
  font-size: 16px;
}

And that’s it for the basics. We have learned how to create basic HTML structures and apply styles to the elements.

Hello, Real Development World!

This chapter aims to address the following questions:

  1. How can we access tags like ‘h1,’ ‘section,’ and others? What is the approach to retrieve them?

  2. How can we customise styles for specific elements rather than applying them to an entire group, such as ‘text’ or ‘image’? Just custom classes and good old BEM?

  3. While the basic structures are straightforward to implement, what about more complex examples like lists, grids, layouts or custom structures?

Each content element can be customised using its fundamental properties, including:

  • Tag

  • Modifiers

  • Content

Additionally, there are other properties that can be applied to elements:

  • Config 
    This serves as an alternative entry point for all content element properties, with the highest priority.

  • If
    This property filters the element by converting the provided value into a boolean.

Tag

The ‘tag’ property is used to override a default tag.

import CE from 'react-content-elements';

<CE.Text tag="h1">Rule your mind or it will rule you.</CE.Text>
// HTML
<h1 class="ce ce-text">Rule your mind or it will rule you.</h1>

Modifiers

You can extend the list of Content Element classes using the ‘modifiers’ property.

import CE from 'react-content-elements';

<CE.Link className="nav-link" modifiers={['bold']}>Navigation Link</CE.Text>
<CE.Link className="nav-link" modifiers={['bold', 'active']}>Active Navigation Link</CE.Text>
// HTML
<a class="nav-link ce ce-link ce--bold">Navigation Link</a>
<a class="nav-link ce ce-link ce--bold ce--active">Active Navigation Link</a>

Classes generated by modifiers are selected by following SASS mixins:

@use 'react-content-element/styles/utils' as *;

/* by content element modifier */
@include byModifier('bold') {
  font-weight: bold;
}
// CSS
.ce--bold {
  font-weight: bold;
}

/* by selector with content element modifier */
.nav-link {
  @include withModifier('active') {
    color: red;
  }
}
// CSS
.nav-link.ce--active {
  color: red;
}

Modifiers can be used to change the default behavior of elements as well, such as overriding a default tag:

import CE from 'react-content-elements';

<CE.Text modifiers={['title']}>Be yourself; everyone else is already taken.</CE.Text>
// HTML
<h3 class="ce ce-text ce--title">Be yourself; everyone else is already taken.</h3>

The list of default and modified tags should be provided via Content Element config:

import CE from 'react-content-elements';

CE.setup({
 tags: {
   byName: {
     'text': 'p',
   },
   byModifier: {
     'title': 'h3',
   },
 },
})

Modifiers have a handy feature for responsive layouts:

  • Above & Beyond
    above-[breakpoint-name] - styles are applied for 
    screen size ≥ [breakpoint-value-by-name]
    beyond-[breakpoint-name]
    - styles are applied for 
    screen size < [breakpoint-value-by-name]

import CE from 'react-content-elements';

<CE.Text modifiers={["title-above-xl", "accent-beyond-sm"]}>Don't be dead serious about your life – it's just a play.</CE.Text>
// HTML
<p class="ce ce-text ce--title-above-xl ce--accent-beyond-sm">Don't be dead serious about your life – it's just a play.</p>

<CE.Block modifiers={["row-above-md", "section-below-xl"]}>The way you speak to yourself matters.</CE.Block>
// HTML
<div class="ce ce-block ce--row-above-md ce--section-below-xl">The way you speak to yourself matters.</div>

Content

This property stands for the inner HTML of your element. It will override the data passed as a children property.

import CE from 'react-content-elements';

<CE.Text content="Simplicity is the ultimate sophistication."/>
// HTML
<p class="ce ce-text">Simplicity is the ultimate sophistication.</p>

<CE.Text content="Content by property">Creativity is intelligence having fun.</CE.Text>
// HTML
<p class="ce ce-text">Content by property</p>

Config

This object is merged with all the properties passed inline. Config values have top priority and will be applied as a result.

import CE from 'react-content-elements';

<CE.Text config={[ modifiers: ['accent'], tag: 'h2' ]}>Simple example with config</CE.Text>
// HTML
<h2 class="ce ce-text ce--accent">Simple example with config</h2>

<CE.Text
  tag="h3"
  modifiers={['bold']}
  config={[ modifiers: ['accent'], tag: 'h2', content: '<i>Content by config</i>' ]}
>
  Another example with config
</CE.Text>
// HTML
<h2 class="ce ce-text ce--accent"><i>Content by config</i></h2>

If

The boolean value that is used to filter out the elements by condition. If a falsy value is passed, the element is not rendered.

import CE from 'react-content-elements';

<CE.Text if={0}>Nothing is impossible</CE.Text>
// HTML
// The element is not rendered

<CE.Text if={1}>Everything is possible</CE.Text>
// HTML
<p class="ce ce-text">Everything is possible</p>

Now that you have learned the basics and methods to customise the elements, let’s switch to more complicated structures. We are going to explore the following elements:

  • List

  • Custom

List

HTML List element structure involves two elemens(ul and li).

This is how you can get it via Content Elements.

import CE from 'react-content-elements';

<CE.List />
// HTML
<ul class="ce ce-list"></ul>

<CE.List>
  <CE.Text>1st item</CE.Text>
  <CE.Text>2nd item</CE.Text>
</CE.List>
// HTML
<ul class="ce ce-list">
  <li class="ce ce-item">
    <p class="ce ce-text">1st item</p>
  </li>
  <li class="ce ce-item">
    <p class="ce ce-text">2nd item</p>
  </li>
</ul>

<CE.List
  items={[{ content: '1st item', modifiers: ['accent'] }, { content: '2nd item', tag: 'span' }]}
  ItemTemplate={CE.Text}
/>
// HTML
<ul class="ce ce-list">
  <li class="ce ce-item">
    <p class="ce ce-text ce--accent">1st item</p>
  </li>
  <li class="ce ce-item">
    <span class="ce ce-text">2nd item</span>
  </li>
</ul>

Custom

In case if required structure(Content Element) is missing out of the box you can extend the default list with your own Custom Content Element.

There is a utility function getCEClassName to generate the base class by element name:

import { getCEClassName } from 'react-content-elements';

getCEClassName('example', ['modifier', false && 'another-modifier']);
// 'ce ce-example ce--modifier'
/* custom element */
const CustomTable = ({
  className,
  headerCellModifiers,
  cellHeaders,
  rowsData,
}) => {
  const baseClassName = getCEClassName('custom-table');
  const trHeaderClassName = getCEClassName('custom-table-header');
  const thClassName = getCEClassName('custom-table-cell', headerCellModifiers);

  const trClassName = getCEClassName('custom-table-row');
  const tdClassName = getCEClassName('custom-table-cell');

  const TableRow = ({ rowData }: any) => (
    <tr className={trClassName}>
      {rowData.map((rowValue: string, rowID: string) => (
        <td key={rowID} className={tdClassName}>
          {rowValue}
        </td>
      ))}
    </tr>
  );

  return (
    <table className={[className, baseClassName].join(' ')}>
      <thead>
        <tr className={trHeaderClassName}>
          {cellHeaders.map((header: string, headID: string) => (
            <th key={headID} className={thClassName}>
              {header}
            </th>
          ))}
        </tr>
      </thead>
      <tbody>
        {rowsData.map((rowData: string, rowID: string) => (
          <TableRow rowData={rowData} key={rowID} />
        ))}
      </tbody>
    </table>
  );
};

/* usage of custom element */
const headers = ['header 1', 'header 2', 'header 3', 'header 4'];
const firstRowData = ['cell 1', 'cell 2', 'cell 3', 'cell 4'];
const rowsData = [firstRowData];
const headerCellModifiers = ['bold'];

<CE.Custom
  CustomTemplate={CustomTable}
  cellHeaders={headers}
  rowsData={rowsData}
  headerCellModifiers={headerCellModifiers}
/>

/* HTML */
<table className="ce ce-custom-table">
  <thead>
  <tr className="ce ce-custom-table-header">
    <th className="ce ce-custom-table-cell ce--bold">header 1</th>
    <th className="ce ce-custom-table-cell ce--bold">header 2</th>
    <th className="ce ce-custom-table-cell ce--bold">header 3</th>
    <th className="ce ce-custom-table-cell ce--bold">header 4</th>
  </tr>
  </thead>
  <tbody>
  <tr className="ce ce-custom-table-row">
    <td className="ce ce-custom-table-cell">cell 1</td>
    <td className="ce ce-custom-table-cell">cell 2</td>
    <td className="ce ce-custom-table-cell">cell 3</td>
    <td className="ce ce-custom-table-cell">cell 4</td>
  </tr>
  </tbody>
</table>

Tags:
Hubs:
Total votes 2: ↑2 and ↓0+2
Comments1

Articles