PHPackages                             technoprodev/technoart - 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. [Framework](/categories/framework)
4. /
5. technoprodev/technoart

ActiveLibrary[Framework](/categories/framework)

technoprodev/technoart
======================

No more custom CSS - All in one CSS framework for developing clean, professional &amp; responsive web app.

v0.0.9(7y ago)34MITSCSS

Since Feb 4Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/technoprodev/technoart)[ Packagist](https://packagist.org/packages/technoprodev/technoart)[ Docs](https://technoartcss.com)[ RSS](/packages/technoprodev-technoart/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependenciesVersions (2)Used By (0)

Technoart
=========

[](#technoart)

A constrained CSS utility library. Not a framework, a discipline.

The constraint is the product. Spacing follows a 4pt grid. Breakpoints are fixed. Base components are structural. Colors, brand tokens, and visual opinions belong to your team.

Technoart ships two things: a compiled CSS file, and a philosophy. Use the file, or use just the idea.

Full build is ~125kb. With [PurgeCSS](https://purgecss.com) in production, real-world usage drops this to a few kb.

---

Get Started
-----------

[](#get-started)

**Use the file** - drop in and go.

**CDN:**

```

```

**npm:**

```
npm install technoart
```

```
@import 'technoart/dist/technoart.css';
```

After dropping in the CSS, define your color tokens once in your own stylesheet. Technoart ships no colors. That's intentional. Here's a common starting point:

```
/* your stylesheet, loaded after technoart.css */
:root {
  --color-primary: hsl(182, 70%, 40%);
  --color-text: hsl(235, 12%, 20%);
  --color-bg: hsl(210, 30%, 98%);
  --color-surface: #fff;
  --color-border: hsl(210, 17%, 88%);
  --color-muted: hsl(208, 17%, 55%);
}
body {
  color: var(--color-text);
  background: var(--color-bg);
  font-family: system-ui, sans-serif;
}
```

These aren't Technoart's variables. They're yours. Change the names, change the values, add or remove. The library works with whatever you define. See `demo/index.html` for a working example of this pattern.

---

**Use the idea** - fork and own.

```
index.scss           ← entry point
_variable.scss       ← shared variables (spacing scale, breakpoints)
_mixin.scss          ← mixins
core/                ← individual utility files
demo/index.html      ← visual reference for every utility

```

```
git clone https://github.com/yourusername/technoart
npm install
npm run build        # compile to dist/technoart.css
npm run dev          # watch mode
```

Modify `_variable.scss` to adjust the spacing scale, breakpoints, or structural defaults. A team that forks Technoart now owns their system. That's the intended outcome.

---

Breakpoints
-----------

[](#breakpoints)

Three fixed breakpoints. **Breakpoint suffix = that size and below** (`max-width`).

SuffixValueApplies when`-sm`640px≤ 640px`-md`768px≤ 768px`-lg`1024px≤ 1024px```

...

...
```

One direction only. Base styles are your default (typically desktop). Breakpoint suffixes are overrides for smaller screens. The only exception is [Hidden](#hidden), which supports both directions by design.

**Why desktop-first and not mobile-first?**

Tailwind and most utility frameworks default to mobile-first, where `md:` means 768px and above. Technoart defaults to desktop-first, where `-md` means 768px and below.

Web apps are primarily desktop experiences. The base style is what most users see most of the time. Mobile is an override. Desktop-first reads naturally for app UIs: "this is the layout, on smaller screens it adapts." Mobile-first makes more sense for content sites where the reading experience starts on phone. For app development, write the default first, add breakpoint suffixes as exceptions.

---

Spacing
-------

[](#spacing)

4pt grid. Responsive: yes

Values: `0, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 80, 100, 120, 140`

> `2` is a deliberate exception, outside the 4pt grid, useful for hairline gaps and micro-nudges.

ClassCSS`.margin-{n}``margin: {n}px``.margin-x-{n}``margin-left + margin-right: {n}px``.margin-y-{n}``margin-top + margin-bottom: {n}px``.margin-top-{n}``margin-top: {n}px``.margin-right-{n}``margin-right: {n}px``.margin-bottom-{n}``margin-bottom: {n}px``.margin-left-{n}``margin-left: {n}px``.margin-auto``margin: auto``.margin-x-auto``margin-left: auto; margin-right: auto``.margin-y-auto``margin-top: auto; margin-bottom: auto``.margin-{top|right|bottom|left}-auto`single side auto`.padding-{n}``padding: {n}px``.padding-x-{n}``padding-left + padding-right: {n}px``.padding-y-{n}``padding-top + padding-bottom: {n}px``.padding-top-{n}``padding-top: {n}px``.padding-right-{n}``padding-right: {n}px``.padding-bottom-{n}``padding-bottom: {n}px``.padding-left-{n}``padding-left: {n}px````
...
```

---

Size
----

[](#size)

Same 4pt grid for fixed pixel sizes. Responsive: yes

Pixel values: `0, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 80, 100, 120, 140`

ClassCSS`.size-{n}px``width: {n}px; height: {n}px``.width-{n}px``width: {n}px``.height-{n}px``height: {n}px``.icon-{n}``font-size: {n}px` (for icon fonts)Percentage values: `0, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80, 90, 100`

ClassCSS`.width-{n}``width: {n}%``.height-{n}``height: {n}%``.width-1-3` / `.width-2-3``width: 33.33%` / `width: 66.66%``.height-1-3` / `.height-2-3``height: 33.33%` / `height: 66.66%``.width-100v` / `.height-100v``width: 100vw` / `height: 100vh``.width-auto` / `.height-auto``width: auto` / `height: auto``.min-width-0` / `.min-width-100``min-width: 0` / `min-width: 100%``.max-width-0` / `.max-width-100``max-width: 0` / `max-width: 100%``.min-height-0` / `.min-height-100``min-height: 0` / `min-height: 100%``.max-height-0` / `.max-height-100``max-height: 0` / `max-height: 100%``.min-width-100v` / `.max-width-100v`viewport units`.min-height-100v` / `.max-height-100v`viewport units---

Typography
----------

[](#typography)

Heading and body size utilities. Apply to any element. Responsive: yes

Classfont-sizeline-height`.h1`40px44px`.h2`32px36px`.h3`28px32px`.h4`24px28px`.h5`20px24px`.h6`18px22px`.text-body-1`16px24px`.text-body-2`14px20px`.text-body-3`12px16px`.text-body-4`10px16px**Alignment** - Responsive: yes

`.text-left` `.text-center` `.text-right` `.text-justify`

**Wrapping** - Responsive: yes

`.text-wrap` `.text-nowrap` `.text-ellipsis`

**Decoration** - Responsive: yes

`.text-line-none` `.text-strike` `.text-underline` `.hover-text-underline` `.hover-text-line-none` `.hover-text-strike`

**Weight** - Responsive: yes

`.font-weight-100` through `.font-weight-800`, `.font-weight-normal`, `.font-weight-bold`

**Transform / Style** - Responsive: no

`.text-uppercase` `.text-lowercase` `.text-capitalize` `.font-style-italic` `.font-style-normal`

**Other** - Responsive: no

`.line-height-1` `.letter-spacing-2` `.cursor-pointer` `.cursor-default` `.cursor-progress` `.cursor-not-allowed` `.ul-square` `.ul-unstyled`

```
Responsive heading size
Smaller on mobile
```

---

Flex
----

[](#flex)

Responsive: yes

**Container**

`.flex` `.inline-flex`

**Direction**

`.flex-row` `.flex-column` `.flex-row-reverse` `.flex-column-reverse`

**Wrap**

`.flex-wrap` `.flex-nowrap`

**Justify Content** (main axis)

`.flex-justify-start` `.flex-justify-end` `.flex-justify-center` `.flex-justify-between` `.flex-justify-around`

**Align Items** (cross axis)

`.flex-items-start` `.flex-items-end` `.flex-items-center` `.flex-items-baseline` `.flex-items-stretch`

**Align Content** (multi-row)

`.flex-content-start` `.flex-content-end` `.flex-content-center` `.flex-content-between` `.flex-content-around` `.flex-content-stretch`

**Gutter** - values: `0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40`

`.flex-gutter-{n}` `.flex-gutter-x-{n}` `.flex-gutter-y-{n}`

> Gutter uses negative margin on the container + padding on children. Don't add padding to children separately.

**Align Self** (on children)

`.align-auto` `.align-start` `.align-end` `.align-center` `.align-baseline` `.align-stretch`

**Grow / Shrink**

`.grow-0` `.grow-1` `.shrink-0` `.shrink-1`

**Fill**

`.fill`: `flex: 1 1 auto` (fills available space) `.equal`: `flex: 1 0 0%` (equal width with siblings)

**Order**

`.order-min-1` `.order-0` `.order-1` `.order-2` `.order-3` `.order-4` `.order-5`

```

  ...
  ...

```

---

Border
------

[](#border)

Responsive: yes

ClassCSS`.border``border: 1px solid currentColor``.border-x`left + right`.border-y`top + bottom`.border-top``border-top: 1px solid currentColor``.border-right``border-right: 1px solid currentColor``.border-bottom``border-bottom: 1px solid currentColor``.border-left``border-left: 1px solid currentColor``.border-none``border: none``.border-width-2` / `-3` / `-4``border-width: 2px / 3px / 4px`Border color follows `currentColor`. Set `color` on the element and the border matches automatically. Source users can replace `currentColor` directly in `core/_border.scss` with any value: a CSS variable, a hex, a token from their own system.

---

Border Radius
-------------

[](#border-radius)

Responsive: no

Values: `0, 4, 8, 16, 9999`

ClassCSS`.rounded-{n}``border-radius: {n}px``.circle``border-radius: 50%`> `9999` is the pill value, fully rounded ends on any element regardless of height. Base only, no individual corners, no responsive variants.

---

Opacity
-------

[](#opacity)

Responsive: yes

`.opacity-02` `.opacity-04` `.opacity-06` `.opacity-08` `.opacity-1`

---

Overflow
--------

[](#overflow)

Responsive: yes

`.overflow-auto` `.overflow-x-auto` `.overflow-y-auto``.overflow-hidden` `.overflow-x-hidden` `.overflow-y-hidden``.overflow-visible` `.overflow-x-visible` `.overflow-y-visible``.overflow-scroll-hidden`

---

Positioning
-----------

[](#positioning)

Responsive: yes

**Display**: `.block` `.inline-block` `.inline`

**Position**: `.static` `.relative` `.absolute` `.fixed` `.sticky`

**Offset**: `.top-0` `.right-0` `.bottom-0` `.left-0` `.top-100` `.right-100` `.bottom-100` `.left-100` `.top-auto` `.right-auto` `.bottom-auto` `.left-auto`

**Center shortcuts**: `.center-x` (horizontal) `.center-y` (vertical) `.center` (both)

**Z-index**: `.z-min-2` `.z-min-1` `.z-0` `.z-1` `.z-2` `.z-3` `.z-4` `.z-5` `.z-6` `.z-7` `.z-8` `.z-9` `.z-max` `.z-unset`

---

Shadow
------

[](#shadow)

Responsive: yes

Class`.shadow-none`removes shadow`.shadow-1` `.shadow-2` `.shadow-3` `.shadow-4`increasing elevation`.hover-shadow-1` through `.hover-shadow-4`on `:hover``.active-shadow-1` through `.active-shadow-4`on `:active`---

Hidden
------

[](#hidden)

**Breakpoint suffix = that size and below** (max-width, same as all utilities). **`-greater` suffix = that size and above** (min-width, exception for visibility control only).

ClassApplies when`.hidden`always`.hidden-sm`≤ 640px`.hidden-md`≤ 768px`.hidden-lg`≤ 1024px`.hidden-sm-greater`≥ 640px`.hidden-md-greater`≥ 768px`.hidden-lg-greater`≥ 1024px`.hidden-print`when printing`.hidden-screen`when on screen```

Mobile only

Desktop only
```

No `.visible-*` class exists or is needed. Use `hidden` on the element that should disappear, not on the one that should appear.

---

Scroll Locked
-------------

[](#scroll-locked)

Locks body scroll. Use for modals, drawers, overlays.

```
...
```

---

Container
---------

[](#container)

Centered, max-width containers.

ClassMax-width`.container-1320`1320px`.container-960`960px---

Button
------

[](#button)

Structural base only. No color, no size, no padding. Those are yours.

```
Label
Link styled as button
```

Provides: `display: inline-block`, `text-align: center`, `text-decoration: none`, `user-select: none`, `background-color: transparent`, `border: 1px solid currentColor`, `border-radius: 4px`, `cursor: pointer`, disabled state.

`border: 1px solid currentColor` means the border always matches the element's `color`. Set `color` on the button and the border follows, no separate override needed. On a blank page this renders as black (browser default), which is correct and intentional.

Your team defines size, color, shape, and variants.

---

Form
----

[](#form)

Structural base for form controls. No color, no visual opinion.

ElementClassText input`.form-text`Textarea`.form-textarea`Select / Dropdown`.form-dropdown`Checkbox (stroke style)`.form-checkbox.form-checkbox-stroke`Checkbox (fill style)`.form-checkbox.form-checkbox-fill`Radio (stroke style)`.form-radio.form-radio-stroke`Radio (fill style)`.form-radio.form-radio-fill`Toggle`.form-toggle````

   Option

```

---

Table
-----

[](#table)

ClassDescription`.table`Base table`.table.table-compact`Reduced cell padding`.table.table-bordered`All cell borders`.table.table-border-none`No borders`.table.table-striped`Alternating row background`.table.table-hovered`Row highlight on hover`.table .th-shrink`Column shrinks to content width`.table .th-expand`Column expands to fill available space---

Skeleton
--------

[](#skeleton)

Apply `.skeleton` to leaf elements inside the component being loaded, not a separate skeleton component.

```

```

**Why not a separate skeleton component?** A separate `ArticleCardSkeleton` has a different DOM structure than the real `ArticleCard`. When real content loads and the skeleton swaps out, the layout shifts, which is a CLS (Cumulative Layout Shift) regression. Using `.skeleton` on the same component structure guarantees an identical layout, so the shift is zero.

Skeleton exposes two CSS custom properties:

PropertyDefaultDescription`--skeleton-bg``#E7E7E7`Base background color`--skeleton-shimmer``rgba(255,255,255,0.35)`Shimmer highlight, expects an rgba value```
:root {
  --skeleton-bg: #D8D8D8;
  --skeleton-shimmer: rgba(255, 255, 255, 0.5);
}
```

Source users can override `$skeleton-animation-duration` (default `3s`) before import.

---

Animate
-------

[](#animate)

Usage pattern: attach `.animate` as a base, then add animation and modifier classes:

```
...
```

**Animation types**: `fade-in`, `fade-in-down`, `fade-in-left`, `fade-in-right`, `fade-in-up`, `fade-out`, `fade-out-down`, `fade-out-left`, `fade-out-right`, `fade-out-up`, `slide-in-down`, `slide-in-left`, `slide-in-right`, `slide-in-up`, `slide-out-*`, `zoom-in`, `zoom-out`

**Modifiers**: `.repeat-1` `.repeat-2` `.repeat-3` / `.delay-1s` `.delay-2s` `.delay-3s` / `.speed-02s` `.speed-04s` `.speed-06s` `.speed-08s` `.speed-2s` `.speed-3s`

---

Group-Show
----------

[](#group-show)

Behavioral utility. Shows child elements conditionally when a parent is hovered or focused.

```

  Hover me
  Visible only on parent hover

```

Classes: `.group-hover-show` `.group-focus-show` `.group-show` (hover + focus)

Two caveats: `.group-focus-show` uses `:not(:focus)`. For this to work on a non-interactive element like a `div`, add `tabindex="0"`. And because visibility is toggled with `display:none`, it cannot be CSS-transitioned, so combining with `.animate` will not produce a fade-in.

---

Contributing
------------

[](#contributing)

Technoart is deliberately opinionated. PRs that add utility values, breakpoints, or configuration options are unlikely to be merged. The constraint is the product.

Bug fixes, documentation improvements, and demo page additions are welcome.

---

License
-------

[](#license)

MIT

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance56

Moderate activity, may be stable

Popularity7

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 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

2657d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/61fbf605d9110fc22a3b6f056fca3b5a2b399d1eeef07590be6f36ce336454f7?d=identicon)[technoprodev](/maintainers/technoprodev)

![](https://www.gravatar.com/avatar/9785ed53d3ea5fd417d94c3d4e74a509d83d9428ce39ca8b970feeaf9af1b00b?d=identicon)[prafandy](/maintainers/prafandy)

---

Top Contributors

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

---

Tags

all-in-oneappcleancssframeworkjsno-dependenciesprofessionalreliableresponsivesasssimplewebframeworkwebcssJSsassSimplecleanappresponsiveno-dependenciesprofessionalall-in-onereliable

### Embed Badge

![Health badge](/badges/technoprodev-technoart/health.svg)

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

###  Alternatives

[twbs/bootstrap

The most popular front-end framework for developing responsive, mobile first projects on the web.

174.1k17.6M327](/packages/twbs-bootstrap)[twitter/bootstrap

The most popular front-end framework for developing responsive, mobile first projects on the web.

174.1k1.7M27](/packages/twitter-bootstrap)[zurb/foundation

The most advanced responsive front-end framework in the world.

29.8k380.2k15](/packages/zurb-foundation)[foundation/foundation-sites

The most advanced responsive front-end framework in the world.

29.8k8.4k](/packages/foundation-foundation-sites)[coreui/coreui

The most popular front-end framework for developing responsive, mobile-first projects on the web rewritten and maintain by the CoreUI Team

873111.6k4](/packages/coreui-coreui)[components/bootstrap

The most popular front-end framework for developing responsive, mobile first projects on the web.

932.8M63](/packages/components-bootstrap)

PHPackages © 2026

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