npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@konce-pt/grid

v0.7.0

Published

Mobile-first layout system for Koncept UI — CSS Grid columns, flexbox utilities and container queries driven by custom properties. Framework-agnostic (SCSS source).

Readme

@konce-pt/grid

Mobile-first layout system for Koncept UI — CSS Grid columns, flexbox utilities, gap and order. Plain CSS: no framework, no runtime.

Utility classes set custom properties only. A fixed number of @media rules turns them into a layout, so the stylesheet grows with the number of breakpoints, not with the number of columns — and changing a span never touches a class in the DOM.

  • Install: pnpm add @konce-pt/grid
  • License: MIT

Setup

// Vite / webpack — order matters
import '@konce-pt/tokens/css';
import '@konce-pt/tokens/css/dark';
import '@konce-pt/styles';
import '@konce-pt/grid';

With the Angular CLI put the files in angular.jsonstyles[] in the same order instead of importing them in main.ts.

SCSS source: @use 'pkg:@konce-pt/grid/scss';

Quick start

<div class="kpt-grid">
  <div class="kpt-col-12 kpt-col-sm-6 kpt-col-md-4">Card 1</div>
  <div class="kpt-col-12 kpt-col-sm-6 kpt-col-md-4">Card 2</div>
  <div class="kpt-col-12 kpt-col-md-4">Card 3</div>
</div>

With Angular, @konce-pt/angular/grid adds directives with signal inputs:

<div kptGrid>
  <div [kptCol]="12" [kptColSm]="6" [kptColMd]="4">Card 1</div>
</div>

Breakpoints

Breakpoints are design tokens shared with the rest of the library. Mobile-first: a value applies from its breakpoint upwards until another one overrides it, so kpt-col-12 kpt-col-lg-5 is 12 on mobile, sm and md, and 5 only from lg.

| Token | From | Class | | --- | --- | --- | | — | 0 | kpt-col-6 | | --kpt-breakpoint-sm | 640px | kpt-col-sm-6 | | --kpt-breakpoint-md | 768px | kpt-col-md-6 | | --kpt-breakpoint-lg | 1024px | kpt-col-lg-6 | | --kpt-breakpoint-xl | 1280px | kpt-col-xl-6 | | --kpt-breakpoint-2xl | 1536px | kpt-col-2xl-6 |

@media cannot read var(), so the rules need compile-time values. The build injects them straight from the token source (scripts/gen-tokens.mjssrc/_tokens.generated.scss), which keeps the tokens the single source of truth while leaving src/ self-contained — recompiling it needs no resolution of bare imports into node_modules.

Classes

Every class has per-breakpoint variants in the shape kpt-<util>-<bp>-<value>: kpt-col-md-6, kpt-justify-lg-between, kpt-gap-md-6, kpt-order-md-none.

| Group | Classes | | --- | --- | | Layout | kpt-grid · kpt-container · kpt-form-grid | | Columns | kpt-col-1…12 · kpt-col-full · kpt-col-auto · kpt-col-start-1…12 | | Display | kpt-flex · kpt-flex-inline | | Direction | kpt-flex-row · -row-reverse · -column · -column-reverse | | Wrap | kpt-flex-wrap · -nowrap · -wrap-reverse | | Flex item | kpt-flex-1 · -auto · -initial · -none · kpt-grow-0/1 · kpt-shrink-0/1 | | Justify | kpt-justify-start · -end · -center · -between · -around · -evenly | | Align items | kpt-align-start · -end · -center · -baseline · -stretch | | Align content | kpt-content-start · -end · -center · -between · -around · -evenly | | Align self | kpt-self-auto · -start · -end · -center · -stretch · -baseline | | Gap | kpt-gap-0…16 · kpt-gap-x-* · kpt-gap-y-* | | Order | kpt-order-first · -last · -none · kpt-order-1…12 |

How many columns?

Twelve out of the box. Two ways to change that, solving different problems.

At runtime — one grid or the whole app, no recompilation:

:root { --kpt-grid-columns: 18; }
<div class="kpt-grid" style="--kpt-grid-columns:18">…</div>

Utility classes stop at kpt-col-12, because classes cannot be generated at runtime. For spans above 12 set the variable inline (style="--kpt-col:15") or use the [kptCol] directive, which does exactly that.

At build time — the whole app, with the full set of classes:

// src/styles.scss — generates kpt-col-1 … kpt-col-18 and every breakpoint variant
@use 'pkg:@konce-pt/grid/scss' with ($columns: 18);

The pkg: prefix is how Sass resolves a package exports entry; the Angular CLI and Vite understand it out of the box, and the Sass CLI needs --pkg-importer=node. Without it, point Sass at the file and add node_modules to the load path: @use '@konce-pt/grid/src/index' with ($columns: 18);

When you compile the source, do not also import @konce-pt/grid — both stylesheets would end up in the bundle.

Container mode

<div class="kpt-grid" data-container>…</div>

Spans follow the width of the grid itself instead of the window, so a card in a narrow sidebar stacks even when the viewport is wide.

A limitation of CSS, not of this package: @container queries the nearest ancestor container, so an element cannot query its own. Spans, start, order and self follow the container; column count and gaps still follow the viewport.

Form layout

<form class="kpt-grid kpt-form-grid">
  <kpt-form-field label="First name">…</kpt-form-field>
  <kpt-form-field label="Last name">…</kpt-form-field>
  <kpt-form-field label="Notes" class="kpt-col-md-12">…</kpt-form-field>
</form>

Children stack on mobile and split into two columns from md, with no classes of their own. The preset uses :where(), so its specificity is zero — any utility class or [kptCol] overrides it, as the notes field does above.

Cascade layers

Rules live in kpt.utilities, the highest of the declared layers (kpt.reset < kpt.base < kpt.components < kpt.utilities). They therefore win over component styles, while your own rules outside any layer win over them — no specificity war, no !important.

Custom properties

| Property | Scope | Description | | --- | --- | --- | | --kpt-grid-columns | grid | Column count. Inherits, so it can be set once on :root. | | --kpt-gap | grid | Gap on both axes. | | --kpt-gap-x / --kpt-gap-y | grid | Gap on one axis — overrides --kpt-gap. | | --kpt-justify / --kpt-align / --kpt-content | grid | Box alignment. | | --kpt-flex-direction / --kpt-flex-wrap | grid | Flex container axis and wrapping. | | --kpt-container-padding | grid | Horizontal padding of .kpt-container. | | --kpt-col | column | Column span — the mobile-first base. | | --kpt-col-start | column | Grid line the column starts on (1-based); this is how offsets work. | | --kpt-order | column | Visual order. Does not change the DOM. | | --kpt-self | column | align-self of a single child. | | --kpt-flex / --kpt-grow / --kpt-shrink | column | Flex item sizing. |

Every property has per-breakpoint variants in the same shape: --kpt-col--kpt-col-md.

Accessibility

order is visual only. Screen readers and keyboard navigation follow the DOM, so do not use it to move interactive content — reorder the markup instead.