---
name: bulma-java
description: Use when writing Java code that generates HTML with Bulma CSS components using the bulma-java library (com.github.t1:bulma-java). Triggers include imports of com.github.t1.bulmajava or com.github.t1.htmljava, or when generating server-side HTML with Bulma styling.
---
# bulma-java
Type-safe, fluent Java API for generating HTML with Bulma CSS components. Zero runtime dependencies in core.
## Maven
```xml
com.github.t1bulma-java${bulma-java.version}
```
This is the only dependency you need. It transitively includes `java-html` which provides the core HTML elements (`div`,
`ul`, `li`, `span`, `p`, `strong`, `em`, `html`, etc.) — all under the `com.github.t1.htmljava` package. Both packages are part of the
same library.
## Quick Reference — Imports
```java
// Core HTML (provided by java-html, included transitively)
import static com.github.t1.htmljava.Html.html;
import static com.github.t1.htmljava.HtmlBasics.*; // div, span, p, ul, li, h1-h6, strong, em, nav, header, footer, etc.
import static com.github.t1.htmljava.Anchor.a;
// Bulma layout
import static com.github.t1.bulmajava.layout.Section.section;
import static com.github.t1.bulmajava.layout.Container.container;
import static com.github.t1.bulmajava.layout.Hero.hero;
// Bulma columns
import static com.github.t1.bulmajava.columns.Columns.columns;
import static com.github.t1.bulmajava.columns.Column.column;
// Bulma elements
import static com.github.t1.bulmajava.elements.Title.*; // title(), subtitle()
import static com.github.t1.bulmajava.elements.Button.button;
import static com.github.t1.bulmajava.elements.Box.box;
import static com.github.t1.bulmajava.elements.Tag.*; // tag(), tags(), tagsAddon()
import static com.github.t1.bulmajava.elements.Block.block;
import static com.github.t1.bulmajava.elements.Content.content_;
import static com.github.t1.bulmajava.elements.Delete.delete;
import static com.github.t1.bulmajava.elements.Icon.icon;
import static com.github.t1.bulmajava.elements.Image.*; // image(), img(), figure()
import static com.github.t1.bulmajava.elements.Notification.notification;
import static com.github.t1.bulmajava.elements.ProgressBar.progress;
import static com.github.t1.bulmajava.elements.Table.*; // table(), row(), td(), th(), tbody()
// Bulma components
import static com.github.t1.bulmajava.components.Navbar.navbar;
import static com.github.t1.bulmajava.components.Menu.menu;
import static com.github.t1.bulmajava.components.Breadcrumb.breadcrumb;
import static com.github.t1.bulmajava.components.Dropdown.dropdown;
import static com.github.t1.bulmajava.components.Message.message;
import static com.github.t1.bulmajava.components.Pagination.pagination;
import static com.github.t1.bulmajava.components.Panel.panel;
// Bulma layout (additional)
import static com.github.t1.bulmajava.layout.Footer.footer;
import static com.github.t1.bulmajava.layout.Level.level;
import static com.github.t1.bulmajava.layout.Media.media;
// Bulma grid
import static com.github.t1.bulmajava.grid.Grid.*; // grid(), fixedGrid(), cell()
// Bulma form
import static com.github.t1.bulmajava.form.Form.form;
import static com.github.t1.bulmajava.form.Field.field;
import static com.github.t1.bulmajava.form.Input.input;
import static com.github.t1.bulmajava.form.InputType.*;
import static com.github.t1.bulmajava.form.Checkbox.checkbox;
import static com.github.t1.bulmajava.form.Select.select;
import static com.github.t1.bulmajava.form.Textarea.textarea;
// Modifiers
import static com.github.t1.bulmajava.basic.Color.*; // PRIMARY, LINK, INFO, SUCCESS, WARNING, DANGER
import static com.github.t1.bulmajava.basic.Size.*; // SMALL, NORMAL, MEDIUM, LARGE
import static com.github.t1.bulmajava.basic.Style.*; // LIGHT, DARK, ROUNDED, FULLWIDTH, etc.
```
## Element Types
Type hierarchy: `Renderable` → `AbstractElement` → `Element`
- `HtmlBasics.*` factories (`div()`, `ul()`, `li()`, `span()`, `p()`, etc.) return `com.github.t1.htmljava.Element`
- `Element` extends `AbstractElement` which has all the builder methods: `.content()`, `.attr()`, `.id()`,
`.classes()`, `.style()`, etc.
- `Renderable` is the base interface — has only `.render()`. Use it for return types or collections, but you lose
builder methods.
- Bulma components (`section()`, `container()`, `button()`, etc.) return their own types extending `AbstractElement`
**Use `Element` (not `Renderable`) when you need to chain builder methods:**
```java
import com.github.t1.htmljava.Element;
Element list=ul();
list.content(li("item 1")); // .content() works on Element
list.attr("role","tree"); // .attr() works on Element
list.style("display:none"); // .style() works on Element
list.id("my-list"); // .id() works on Element
list.classes("custom"); // .classes() works on Element
// For mixed collections or return types where you don't need builder methods:
import com.github.t1.htmljava.Renderable;
Renderable fragment = div().content(p("Hello"));
```
**Key `.content()` overloads on `AbstractElement`:**
- `.content(String)` — text content
- `.content(Renderable)` — single child
- `.content(Renderable...)` — varargs children
- `.content(Collection extends Renderable>)` — collection of children
- `.content(Stream extends Renderable>)` — stream of children
**Content querying methods on `AbstractElement`:**
- `.content()` — returns the raw `Renderable` content (null if empty)
- `.contentStream()` — returns `Stream` of all children (empty stream if none)
- `.contentIsA(Class)` — tests if content is of a specific type
- `.contentAs(Class)` — casts content to a specific type
- `.findElement(String className)` — finds child by CSS class, returns `Optional>`
- `.findElement(Predicate>)` — finds child by predicate, returns `Optional`
- `.getOrCreate(String className)` — gets existing child by class or creates a default div
- `.getOrCreate(String className, Supplier)` — gets or creates with custom factory
- `.getOrCreate(Predicate>, Supplier)` — gets or creates with predicate
- `.notClasses(String...)` — removes CSS classes; removes the `class` attribute entirely if empty
- `.hasAttribute(String key)` — checks if attribute with given key exists (on `AbstractElement` directly)
- `.hasAttribute(String key, String value)` — checks if attribute with given key and value exists (on `AbstractElement`
directly)
- `.findAttribute(String name)` — returns `Optional` for the named attribute
- `.attributes()` — returns the `@NonNull Attributes` object (never null)
- `.hasAttribute(String key)` — checks if an attribute with the given key exists
- `.hasAttribute(String key, String value)` — checks if an attribute with the given key and value exists
- `.findAttribute(Predicate)` — returns `Optional`
## Rendering
Call `.render()` on any element. Returns a `String`.
```java
// Full page — produces ...
String page = html("Page Title").body(div().content(p("Hello"))).render();
// Fragment — no doctype/html/head wrapper
String fragment = div().content(p("Hello")).render();
```
## Building Pages
```java
html("My App")
.stylesheet("https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css")
.script("app.js")
.body(
section().content(container().content(
title("Welcome"),
p("Hello world")
))
)
.render();
```
### Adding Body Content
There are several ways to add content to the `` of an `Html` page, each useful in different situations:
**Multiple elements** — the most common case with several top-level children:
```java
html("My App").body(navbar(), section(), footer())
```
**Single element** — when the body has one root element:
```java
html("My App").body(section().content(title("Hello")))
```
**Chained calls** — building up the body incrementally:
```java
html("My App")
.body(navbar())
.body(section())
.body(footer())
```
**Implicit routing** — `content()` on `Html` automatically routes to the body:
```java
html("My App").content(h1("Hello")) // equivalent to .body(h1("Hello"))
```
**Body with attributes** — when you need classes or attributes on the `` tag itself,
pass an explicit `Body` element via `content()`:
```java
html("My App").content(body().has(NAVBAR_FIXED_TOP).content(
container().content(section().content(title("Hello")))
))
```
**Functional modification** — an alternative for setting body attributes inline:
```java
html("My App").body(e -> e.classes("custom").content(h1("Hello")))
```
**Positional insertion** — insert at a specific position (0 = first):
```java
html("My App").body(section()).body(navbar(), 0) // navbar before section
```
**Retrieve and mutate** — get the existing body element for later modification:
```java
var page = html("My App").body(section());
page.body().content(footer()); // add to existing body
```
## Custom Attributes
```java
div().
id("main").
classes("custom-class").
attr("data-value","42").
attr("hx-get","/api")
a("Link text").
href("/path") // Anchor has a dedicated .href() method
```
## Columns (Responsive)
```java
// Auto-sized columns
columns().
content(
column().
content(p("Left")),
column().
content(p("Right"))
)
// Sized columns — use .classes() for Bulma column size classes
column().
classes("is-one-third").
content(sidebar)
column().
classes("is-two-thirds").
content(main)
// Desktop-only side-by-side (stacks on mobile/tablet)
columns().
classes("is-desktop").
content(
column().
classes("is-one-quarter").
content(sidebar),
column().
content(mainContent)
)
```
Available size classes: `is-1` through `is-12`, `is-one-third`, `is-two-thirds`, `is-one-quarter`, `is-three-quarters`,
`is-half`, `is-narrow`.
## Forms
```java
form().
post("/submit").
content(
field("Username").
content(input(TEXT).
attr("name","user").
placeholder("Enter name")),
field("Email").
content(input(EMAIL).
attr("name","email"))
.
help("We won't share this"),
field("Role").
content(select("role")
.
option("admin","Admin")
.
option("user","User")),
field().
content(button("Submit").
is(PRIMARY))
)
```
Key form patterns:
- `field(label)` creates labeled field with a plain string; `field()` for no label
- `.label(Renderable...)` sets a rich label with arbitrary content (e.g. spans, tags). The label is rendered as
`