We took our cues from a lot of what's happening with the modern web and translated it to generic concepts and a specific implementation; namely, web components and the HTML5 specification. We also had some philosophical inspiration , available in the details.
Elements takes advantage of 8fold Component to give you a lightweight library to:
- generate your own web components,
- generate all elments from the HTML specification,
- ensure your elements have only those attributes that are valid for the element according to the specification,
- ensure the attributes of your elements have a consistent and logical ordering, and
- verify validity of parent-child relationship of elements.
$ composer require 8fold/php-html
Html::h1(Component::text('Hello!')) ->attr('class content-lead');
<h1 class="content-lead"> Hello! </h1>
For more details see 8fold Component.
The method you call is the main HTML element you wish to use, from there, it's up to you.
Why? (The short-ish version.)
Super-duper short: Writing HTML isn't shiny or sexy, but it ain't easy either.
There were some very specific pain points we wanted to resolve with the creation of this library.
- Writing HTML is a pretty tedious task. That's why we (developers) have created all those template engines allowing us to reuse HTML snippets. That's also why the w3c and others are working on web component libraries; literal reusable snippets of HTML, CSS, and interactive scripts for use in any web application.
- Template engines effectively solve the reuse problem, but they don't solve the HTML problem. Namley, there are a lot of rules and ways to write HTML. Some teams try to solve this by creating coding style manuals that everyone should adhere to, which can be very useful in improving readability, but you still have to know the style and adhere to it.
- In a way, the HTML specification from the w3c is a style guide, that a lot of us, frankly, don't seem to read (or even know exists, to be honest). It tells us what elements exist, what attributes they can have, what events they can respond to, what ARIA roles they can have, and what ARIA attributes can be associated with those roles. Oh, and which elements can be parents and children of other elements.
8fold Elements is positioned to (and already does) solve (some of) these pain points.
It groups attributes in terms of common content, event, aria, other, and boolean. Common content attributes include "id", "class", and so on. It will filter out attributes that do not apply to the element being generated, based on the specification for the element. And is poised to be able to do much more…at speed.
The "at speed" piece is important. Given this library is not considered a template engine in and of itself, chances are you will use it either in conjunction with a template engine, building an extension, or both. Therefore, it has to be as fast as possible.
If you decide to make an extension library, as we did, it is recommended you extend the root
Html class, adding your own elements. This gives you access to your elements first, falling back to 8fold Elements (generic HTML) and finally to 8fold Component (generic web-component).
It can also help with readability if you call elements as directly as possible (namespace, as it were). Let's say you have an extension, and it uses
MyComponents as its prefix. You have an element named
my_component and you need it to have a
paragraph and a full web component named
my_web_component for its content. You could (almost) do something like this:
MyComponents::my_component( MyComponents::p(Component::text('Hello ')) , MyComponents::my_web_component(Component::text('World!')) ]);
But, we have found this to be very, very confusing because it reads as if everything is coming from our own library. Instead, we recommend you do something like this (it will also be marginally faster):
MyComponents::my_component([ Html::p(Component::text('Hello, ')) , Component::my_web_component(Component::text('World!')) ]);
Far less confusing for all involved. It can still get a little dicey if you have two elements from two libraries names the same thing. Therefore, we also recommend that, if you make your own library, just make everything an extension of an HTML element. So, all of you components would be prefixed as if they were web components (
We're working on converting ours to this as well.