PHPackages                             nabeghe/nohtml - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. nabeghe/nohtml

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

nabeghe/nohtml
==============

Say no to HTML — write views in PHP with a clean, simple DSL.

v1.0.1(11mo ago)22MITPHPPHP &gt;=7.4

Since Jun 14Pushed 10mo agoCompare

[ Source](https://github.com/nabeghe/nohtml-php)[ Packagist](https://packagist.org/packages/nabeghe/nohtml)[ Docs](https://github.com/nabeghe/nohtml-php)[ RSS](/packages/nabeghe-nohtml/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (1)Versions (3)Used By (0)

NoHtml for PHP ≥ 7.4
====================

[](#nohtml-for-php--74)

 [![](https://private-user-images.githubusercontent.com/12207627/455145272-fbad06c3-581f-4f42-ac45-004a5939323c.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzU0NzA1MzgsIm5iZiI6MTc3NTQ3MDIzOCwicGF0aCI6Ii8xMjIwNzYyNy80NTUxNDUyNzItZmJhZDA2YzMtNTgxZi00ZjQyLWFjNDUtMDA0YTU5MzkzMjNjLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjA0MDYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwNDA2VDEwMTAzOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFhYWI0MTgyN2YxNjE5MzUzYzA1NmNlMDY5MjUzYzJiM2MxNGU2ZmQ1YWY5ZDI0MmNmNjYwMDQ2ZTNlMGE3NzQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.EsI-Zb0rrlgZfJAcSOcIdYwih0Bkve8jEXzQhRUnOGw)](https://private-user-images.githubusercontent.com/12207627/455145272-fbad06c3-581f-4f42-ac45-004a5939323c.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzU0NzA1MzgsIm5iZiI6MTc3NTQ3MDIzOCwicGF0aCI6Ii8xMjIwNzYyNy80NTUxNDUyNzItZmJhZDA2YzMtNTgxZi00ZjQyLWFjNDUtMDA0YTU5MzkzMjNjLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjA0MDYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwNDA2VDEwMTAzOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFhYWI0MTgyN2YxNjE5MzUzYzA1NmNlMDY5MjUzYzJiM2MxNGU2ZmQ1YWY5ZDI0MmNmNjYwMDQ2ZTNlMGE3NzQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.EsI-Zb0rrlgZfJAcSOcIdYwih0Bkve8jEXzQhRUnOGw)

> Say no to HTML — write views in PHP with a clean, simple DSL.

There are many PHP-based DSLs for HTML out there but **NoHTML** takes a different route in both behavior and structure. At its core, there's a class where each method corresponds to an HTML element. These methods can be used in both static and instance contexts. Each method accepts a variadic list of arguments representing the element’s children. The return value of every method is an instance of the `Nabeghe\NoHtml\Nodes\Element` class, whose methods map to the element's attributes, following a **Fluent Builder** pattern.

🫡 Usage
-------

[](#-usage)

### 🚀 Installation

[](#-installation)

You can install the package via composer:

```
composer require nabeghe/nohtml
```

### Example

[](#example)

In the example below, the NoHtml class is made available via an alias named `N`. You can also access the shared instance using the nohtml() function; however, the below code proceeds in a static manner.

In this code, an HTML element is created right from the start, and then the rest of the page is built around it.

```
use Nabeghe\NoHtml\NoHtml as N;

require 'vendor/autoload.php';

$app = N::html(
    N::head(
        N::meta()->charset('utf-8'),
        N::meta()->name('viewport')->charset('width=device-width, initial-scale=1.0'),
        N::title('No HTML for PHP by Nabeghe'),
        N::script()->src('https://cdn.tailwindcss.com'),
    ),
    N::body(
        N::header(
            N::h1('No HTML for PHP by Nabeghe')->class('text-3xl font-bold'),
            N::nav(
                N::a('Intro')->href('#intro')->class('over:underline'),
                N::a('Table')->href('#table')->class('hover:underline'),
                N::a('Form')->href('#form')->class('hover:underline'),
            )->class('mt-2 space-x-4'),
        )->class('bg-gray-900 text-white py-6 text-center'),
        N::main(
            N::section(
                N::h2('Introduction')->class('text-2xl font-semibold mb-4'),
                N::p(class('mb-4'),
                N::p('This items generated by callback'),
                N::ul([Items::class, 'generate'])->data('template', 'Item {n}')->class('list-disc list-inside mb-4'),
            )->id('intro'),
            N::section(
                N::h2('Details')->class('text-2xl font-semibold mb-4'),
                N::div(
                    N::table(
                        N::tr(
                            N::td('Github')->class([Css::class, 'tableCell']),
                            N::td(
                                N::a('https://github.com/nabeghe/nohtml-php')->href('https://github.com/nabeghe/nohtml-php')->title('No HTML'),
                            )->class([Css::class, 'tableCell']),
                        )->class([Css::class, 'tableRow']),
                        N::tr(
                            N::td('License')->class([Css::class, 'tableCell']),
                            N::td('MIT')->class([Css::class, 'tableCell']),
                        )->class([Css::class, 'tableRow']),
                    )->class('min-w-full border border-gray-300 rounded-md'),
                )->class('overflow-x-auto'),
            )->id('table'),
            N::section(
                N::h2('Contact Us')->class('text-2xl font-semibold mb-4'),
                N::form(
                    N::div(
                        N::label('Name:')->for('name')->class('block font-medium'),
                        N::input()->type('text')->id('name')->name('name')->placeholder('Enter your name')->class('w-full border border-gray-300 rounded px-3 py-2'),
                    ),
                    N::div(
                        N::label('Email:')->for('email')->class('block font-medium'),
                        N::input()->type('text')->id('email')->name('email')->placeholder('Your email')->class('w-full border border-gray-300 rounded px-3 py-2'),
                    ),
                    N::div(
                        N::label('Nessage:')->for('message')->class('block font-medium'),
                        N::textarea()->id('message')->name('message')->placeholder('Type your message here...')->class('w-full border border-gray-300 rounded px-3 py-2'),
                    ),
                    N::div(
                        N::input()->type('checkbox')->id('agree')->name('agree')->placeholder('Your email')->checked(true)->class('h-4 w-4 text-blue-600 rounded'),
                        N::label('I agree to the terms')->for('agree')->class('select-none'),
                    )->class('flex items-center space-x-2'),
                    N::button('Submit')->type('submit')->class('bg-blue-600 text-white rounded px-5 py-2 hover:bg-blue-700 transition'),
                )->action('#')->method('post')->class('space-y-4'),
            )->id('form'),
        )->class('max-w-4xl mx-auto p-6 bg-white mt-6 rounded-lg shadow-md space-y-10'),
        N::footer(
            new Unescapable('&copy; No HTML - Built with ❤️ by https://elatel.ir'),
        )->class('bg-gray-900 text-white text-center py-6 mt-10')
    ),
)->lang('en');

echo '';
echo $app;
```

You can define a child element or an attribute value as a callable, so the actual value can be retrieved at the appropriate time.

Children can be plain strings or anything else — they will be converted to strings. If they are plain strings, they will be escaped, unless the `Nabeghe\NoHtml\Nodes\Unescapable` class is used. Also, a callback defined for children can return a string, an element, or a list of elements. If it returns a string, that string will not be escaped.

As for attributes, a callback can return the value of the attribute. If the value is null, that attribute won’t be set at all. So, if you want an empty value, use an empty string — null means the attribute doesn't exist. Also, if an attribute is set to true or false, no value will be assigned — true simply means the attribute will be present, and false means it won't be there.

**Notice:** Setting children for elements like `` or `` has no effect.

### Callbacks

[](#callbacks)

The class related to the callbacks used in the example above:

```
class Css
{
    public static function tableRow(string $name, El $el)
    {
        return 'hover:bg-gray-100';
    }

    public static function tableCell(string $name, El $el)
    {
        return 'border border-gray-300 px-4 py-2';
    }
}
```

```
class Items
{
    public static function generate(El $el)
    {
        $template = $el->data('template');

        $items = [];
        for ($i = 0; $i < 10; $i++) {
            $n = $i + 1;
            if ($n < 10) {
                $n = '0'.$n;
            }

            $items[] = N::li(str_replace('{n}', "$n", $template));
        }

        return $items;
    }
}
```

📖 License
---------

[](#-license)

Copyright (c) 2025

Licensed under the MIT license, see [LICENSE.md](LICENSE.md) for details.

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance53

Moderate activity, may be stable

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity38

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

Every ~0 days

Total

2

Last Release

338d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dae1bf378bcf40fe55c193160377d613d628188587554a3fb11cdec6f0521ba1?d=identicon)[nabeghe](/maintainers/nabeghe)

---

Top Contributors

[![nabeghe](https://avatars.githubusercontent.com/u/12207627?v=4)](https://github.com/nabeghe "nabeghe (4 commits)")

---

Tags

helperlibraryhtmlDSLsupportnohtmlhtml dsl

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nabeghe-nohtml/health.svg)

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

PHPackages © 2026

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