PHPackages                             cr0w/phml - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. cr0w/phml

ActiveLibrary[Templating &amp; Views](/categories/templating)

cr0w/phml
=========

Composable HTML builder for PHP.

v0.1.0(3mo ago)01MITPHPPHP &gt;=8.2

Since Mar 20Pushed 3mo agoCompare

[ Source](https://github.com/cr0w-digital/phml)[ Packagist](https://packagist.org/packages/cr0w/phml)[ RSS](/packages/cr0w-phml/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (1)Versions (2)Used By (0)

&lt;/ phml
==========

[](#-phml)

A lightweight PHP library for building HTML with functions and arrays.

Installation
------------

[](#installation)

```
composer require cr0w/phml
```

Quick start
-----------

[](#quick-start)

```
require 'vendor/autoload.php';

echo \phml\render(
    h('.card#main',
        h('h1', 'Hello, world!'),
        h('p', 'Built with phml.')
    )
);
```

```

  Hello, world!
  Built with phml.

```

API
---

[](#api)

### `h(string $selector, mixed ...$args): array`

[](#hstring-selector-mixed-args-array)

Builds an HTML node as a plain PHP array. The selector supports Emmet-style shorthand for tag, id, and classes.

```
h('div')                          //
h('p.lead', 'Hello')              // Hello
h('section.full.dark#hero')       //
h('.card#main')                   //   (tag defaults to div)
```

An optional associative array as the first argument sets attributes:

```
h('a', ['href' => '/about', 'class' => 'nav-link'], 'About')
// About
```

Children can be strings, other nodes, arrays of nodes, or `false`/`null` (ignored):

```
$items = array_map(fn($i) => h('li', $i), ['One', 'Two', 'Three']);

h('ul', $items)
// OneTwoThree

h('div', $isAdmin ? h('button', 'Delete') : null)
//
```

---

### `render(mixed $node): string`

[](#rendermixed-node-string)

Serializes a node (or array of nodes) to an HTML string. Text content and attribute values are escaped automatically.

```
render(h('p', 'Hello'))           // Hello
render(h('br'))                   //   (void tags have no closing tag)
render(null)                      // ''
render(false)                     // ''
render([h('li', 'A'), h('li', 'B')]) // AB  (fragment)
```

---

### `c(mixed ...$parts): string`

[](#cmixed-parts-string)

Composes a class string from mixed inputs. Useful for conditional classes.

```
c('btn', 'btn-lg')
// 'btn btn-lg'

c('btn', $isLarge && 'btn-lg')
// 'btn' or 'btn btn-lg'

c('btn', ['btn-primary' => $isPrimary, 'btn-disabled' => $isDisabled])
// 'btn btn-primary'

c(['px-4', ['text-lg' => $big]])
// 'px-4' or 'px-4 text-lg'
```

---

### `e(mixed $value): string`

[](#emixed-value-string)

Escapes a value for safe HTML output. Called automatically by `render()` on all text content and attribute values. Use this when interpolating values outside of `render()`.

```
echo '' . e($pageTitle) . '';
```

---

### `raw(string $html): RawHtml`

[](#rawstring-html-rawhtml)

Marks a string as trusted HTML, bypassing escaping in `render()`. Use only for content you control.

```
render(h('div', raw('trusted')))
// trusted
```

---

Attributes
----------

[](#attributes)

### Boolean attributes

[](#boolean-attributes)

`true` renders the attribute name only. `false` and `null` omit the attribute entirely.

```
h('input', ['type' => 'checkbox', 'checked' => true, 'disabled' => false])
//
```

### Style array

[](#style-array)

An array value for `style` is converted to an inline style string. camelCase keys are kebab-cased automatically.

```
h('div', ['style' => ['marginTop' => '1rem', 'color' => 'red']])
//
```

### Prefix shorthands

[](#prefix-shorthands)

Any attribute key ending in `-` with an array value is expanded as a prefix shorthand. This covers `data-`, `aria-`, `hx-` (HTMX), `x-` (Alpine), `v-` (Vue), or any other framework with no special casing required.

```
h('div', ['data-' => ['userId' => 1, 'role' => 'admin']])
//

h('button', ['aria-' => ['label' => 'Close', 'expanded' => 'false']])
//

h('form', ['hx-' => ['post' => '/submit', 'swap' => 'outerHTML']])
//

h('div', ['x-' => ['data' => '{ open: false }', 'show' => 'open']])
//
```

camelCase subkeys are kebab-cased:

```
h('div', ['hx-' => ['swapOob' => 'true']])
//
```

---

Testing
-------

[](#testing)

```
composer install
composer test
```

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance82

Actively maintained with recent releases

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

95d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/655397?v=4)[cr0w](/maintainers/cr0w)[@Cr0w](https://github.com/Cr0w)

---

Top Contributors

[![cr0w-denny](https://avatars.githubusercontent.com/u/180068927?v=4)](https://github.com/cr0w-denny "cr0w-denny (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/cr0w-phml/health.svg)

```
[![Health](https://phpackages.com/badges/cr0w-phml/health.svg)](https://phpackages.com/packages/cr0w-phml)
```

###  Alternatives

[limenius/react-bundle

Client and Server-side react rendering in a Symfony Bundle

3861.2M](/packages/limenius-react-bundle)[area17/laravel-auto-head-tags

Laravel Auto Head Tags helps you build the list of head elements for your app

4616.0k](/packages/area17-laravel-auto-head-tags)[jelix/wikirenderer

WikiRenderer is a library to generate HTML or anything else from wiki content.

1712.2k1](/packages/jelix-wikirenderer)[webkinder/sproutset

A Composer package for handling responsive images in Roots Bedrock + Sage + Blade projects.

291.8k](/packages/webkinder-sproutset)[awkwardideas/switchblade

Extended blade directives for laravel

102.1k](/packages/awkwardideas-switchblade)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
