.. _creating-pages:
Creating Pages
==============
The :ref:`quickstart:Quickstart` guide shows how to make a simple page using Blu.
This section goes into greater depth on how to generate user interfaces using Blu.
HTML Elements
-------------
The :ref:`quickstart:Quickstart` guide shows how to make a simple page with html, head, and body elements:
.. code-block:: python
from blu.html import body, head, html
def __page__():
return html[
head,
body['Hello World!'],
]
You can import any HTML tag from :mod:`blu.html`:
.. code-block:: python
from blu.html import (
html, head, body, div, span, select, canvas, mymadeuptagname
)
html[
head,
body[
div,
span,
select,
canvas,
mymadeuptagname,
],
]
.. code-block:: html
If the HTML tag name you want to import is a reserved word in Python, add a trailing underscore to the import name:
.. code-block:: python
from blu.html import del_
del_['Hello, World!']
.. code-block:: html
Hello, World!
All non-trailing underscores will be converted to dashes:
.. code-block:: python
from blu.html import tag_name_with_dashes
tag_name_with_dashes['Hello!']
.. code-block:: html
Hello!
In the rare case your desired tagname cannot be imported from the :mod:`blu.html` module, use :func:`blu.create_rare_html_element`.
HTML Attributes
+++++++++++++++
You can set the HTML attributes of an element by calling it as a function:
.. code-block:: python
from blu.html import div
div(id='my-id')
.. code-block:: html
.. note::
Calling an HTML element as a function does not mutate the original; instead, it returns a copy with the new attributes.
.. code-block:: python
from blu.html import div
without_attributes = div
with_attributes = div(a='1', b='2')
without_attributes #
with_attributes #
.. note::
When you set HTML attributes on an element, you completely replace the existing attributes, rather than adding attributes on top:
.. code-block:: python
from blu.html import div
original = div(a='1', b='2')
original(c='3', d='4') #
.. note::
Blu HTML elements take the same attributes as React HTML elements, not native HTML elements (see https://react.dev/reference/react-dom/components for more information):
.. code-block:: python
# Wrong!
div(class='my-class')
# Right.
div(className='my-class')
.. note::
Event-handling attributes like "onClick" are only supported in client-side rendering (see :ref:`user-guide/client-side-rendering:Client-Side Rendering` for more details).
.. code-block:: python
from blu.html import div
def log_clicked(e):
print('Clicked!')
# Only allowed in client-side rendering.
div(onClick=log_clicked)
To include an attribute name that is a reserved word in Python, add a trailing underscore:
.. code-block:: python
from html import form, input, label
form[
label(for_='email-address-input')['Name:'],
input(id='email-address-input'),
]
.. code-block:: html
All non-trailing underscores will be converted to dashes:
.. code-block:: python
from html import input
input(data_value=23)
.. code-block:: html
You can also directly set an attribute name by passing a :py:class:`Mapping ` as the first positional argument:
.. code-block:: python
from html import div
div({'attr_1_': 'value 1'}, attr_2_='value 2')
.. code-block:: html
Children
++++++++
.. include:: /_includes/client-element-children.rst
You can tell Blu that items' positions won't change by putting them in a :py:class:`tuple`. If you do this, you won't have to key the items. For those familiar with React, this is how React `fragments `_ are defined in Blu.