A type-safe PHP library for standards-compliant HTML tag rendering
Build and render block, inline, input, and void elements with immutable fluent APIs.
composer require ui-awesome/html-core:^0.6Renders begin/end tags and full elements using standards-compliant tag enums.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Html;
use UIAwesome\Html\Interop\{Block, Inline, Voids};
echo Html::begin(Block::DIV, ['class' => 'container']);
// <div class="container">
echo Html::inline(Inline::SPAN, 'Hello');
// <span>Hello</span>
echo Html::end(Block::DIV);
// </div><?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Html;
use UIAwesome\Html\Interop\Block;
$content = '<span>Test Content</span>';
echo Html::element(Block::DIV, $content, ['class' => 'test-class']);
// <div class="test-class">
// <span>Test Content</span>
// </div>
echo Html::element(Block::DIV, $content, ['class' => 'test-class'], true);
// <div class="test-class">
// <span>Test Content</span>
// </div>Void tags render without closing tags. Complex attributes (like class arrays and data arrays) are rendered via the
installed ui-awesome/html-helper dependency.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Html;
use UIAwesome\Html\Interop\Voids;
echo Html::void(
Voids::IMG,
[
'class' => ['void'],
'data' => ['role' => 'presentation'],
],
);
// <img class="void" data-role="presentation">Input elements render the input tag with optional prefix and suffix segments through the same template primitives used by inline elements.
<?php
declare(strict_types=1);
namespace App;
use BackedEnum;
use UIAwesome\Html\Core\Element\BaseInput;
use UIAwesome\Html\Interop\{Inline, Voids};
final class SearchInput extends BaseInput
{
protected function getTag(): BackedEnum
{
return Voids::INPUT;
}
protected function run(): string
{
return $this->buildElement();
}
}
echo SearchInput::tag()
->type('search')
->name('q')
->prefix('Search')
->prefixTag(Inline::LABEL)
->render();
// <label>Search</label>
// <input name="q" type="search">Create your own element classes by extending the provided base elements.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Element\BaseBlock;
use UIAwesome\Html\Interop\Block;
use BackedEnum;
final class Div extends BaseBlock
{
protected function getTag(): BackedEnum
{
return Block::DIV;
}
}
echo Div::tag()
->class('card')
->content('Content')
->render();
// <div class="card">
// Content
// </div>BaseBlock supports stack-based begin/end rendering, with protection against mismatched tags.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Element\BaseBlock;
use UIAwesome\Html\Interop\Block;
use BackedEnum;
final class Div extends BaseBlock
{
protected function getTag(): BackedEnum
{
return Block::DIV;
}
}
echo Div::tag()->begin();
echo 'Nested Content';
echo Div::end();
// <div>
// Nested Content
// </div>Inline elements can render prefix and suffix segments, optionally wrapped in their own tags.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Element\BaseInline;
use UIAwesome\Html\Interop\Inline;
use BackedEnum;
final class Span extends BaseInline
{
protected function getTag(): BackedEnum
{
return Inline::SPAN;
}
protected function run(): string
{
return $this->buildElement($this->getContent());
}
}
echo Span::tag()
->content('Content')
->prefix('Prefix')
->prefixTag(Inline::STRONG)
->suffix('Suffix')
->suffixTag(Inline::EM)
->render();
// <strong>Prefix</strong>
// <span>Content</span>
// <em>Suffix</em>Use an immutable Config instance to apply a design-system recipe without global mutable state. Multiple configs can be
used in the same process, and fluent calls made after config() are local overrides.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Config\{Call, ComponentContext, Config, Cookbook, Recipe};
use UIAwesome\Html\Core\Element\BaseInline;
use UIAwesome\Html\Core\Theme\ThemeInterface;
use UIAwesome\Html\Interop\Inline;
use BackedEnum;
final class Span extends BaseInline
{
protected function getTag(): BackedEnum
{
return Inline::SPAN;
}
protected function run(): string
{
return $this->buildElement($this->getContent());
}
}
final readonly class FlowbiteTheme implements ThemeInterface
{
public function getName(): string
{
return 'flowbite';
}
public function getRecipes(ComponentContext $context): iterable
{
if ($context->component === 'badge') {
yield new Recipe(
'flowbite.badge',
new Cookbook(new Call('class', 'rounded text-sm')),
);
}
}
}
$config = new Config(new FlowbiteTheme());
echo Span::tag()
->config($config, new ComponentContext('badge'))
->id('badge-1')
->content('New')
->render();
// <span class="rounded text-sm" id="badge-1">New</span>For a simpler approach without separate provider classes, override loadDefault() in your tag class. These defaults are
applied automatically when tag() is called.
<?php
declare(strict_types=1);
namespace App;
use UIAwesome\Html\Core\Element\BaseBlock;
use UIAwesome\Html\Interop\Block;
use BackedEnum;
final class Container extends BaseBlock
{
protected function getTag(): BackedEnum
{
return Block::DIV;
}
protected function loadDefault(): array
{
return [
'class' => 'container',
];
}
}
echo Container::tag()->render();
// <div class="container">
// </div>
echo Container::tag(['class' => 'container-fluid'])->render();
// <div class="container container-fluid">
// </div>Configuration priority (from weakest to strongest):
- Class defaults from
loadDefault() - Defaults passed to
tag() - Application-scoped recipes applied by
config() - Fluent local overrides called after
config()
This library is agnostic and designed to be extended. You can define your own tag collections (for example, for SVG, MathML, or Web Components) with custom string-backed enums.
Html::element()handles generic open/content/close rendering.Html::inline()handles inline rendering.Html::void()handles void rendering.
You can create a custom enum for your specific domain and use it with html-core.
enum SvgTag: string
{
case SVG = 'svg';
case G = 'g';
// ... add other SVG block tags as needed
}
// now you can use it with the Html renderer or your custom classes
echo Html::element(SvgTag::G, '...');
// <g>...</g>For detailed configuration options and advanced usage.