The Modulo Tutorial: Part 1
Prerequisites: Part 1 and Part 2 of this
tutorial requires a prerequisite knowledge of HTML & CSS only. Part 3
requires familiarity with JavaScript. Familiarity with React, Vue, or similar
frameworks is helpful, but not required.
Welcome to the Modulo tutorial. By following this short tutorial, you can
learn how to use Modulo in your own projects.
When to use Modulo
Modulo is useful when using plain HTML and CSS is no longer sufficient. It
has no dependencies, has no "build process", and does not require experience
with JavaScript, terminal applications, or NPM. This means it can
be equally easily incorporated into a plain HTML "static site" (e.g. when you
assemble HTML, CSS, and other static assets in a directory), or into a
"multi-page" web app built with a backend language or MVC framework.
Ready to dive into Web Component development with
Modulo?
#
1. Components
JS file alternatives:
- Directly link to a CDN hosting Modulo.js (shown here)
- Manually download the Modulo.js file to a JS or asset directory,
e.g.
src="/js/Modulo.js"
(good for offline work)
- Including a pre-rendered "self-bundled" Modulo "build"
(speediest for production, covered in Part 2)
Including Modulo
The first step is to include a Modulo script tag in your HTML file. You
could either start with an empty file, or open up an existing HTML file, and
paste in the following:
<script src="https://unpkg.com/mdu.js"></script>
This will only include the JS file, but not activate Modulo. To activate
Modulo, we need to add the Modulo
, attribute to the script tag,
and leave some space to indicate that this will (soon) contain Modulo code:
<script Modulo src="https://unpkg.com/mdu.js">
</script>
Note that technically, either modulo
or Modulo
will work because HTML is case-insensitive; however, the capitalized
Modulo
spelling is recommended for easier reading.
Why use "components"? Have you ever repeated the same
HTML, CSS, and/or JavaScript while writing a website or or web app?
Components let you store repeated code in one place. Once defined,
components can be re-used everywhere, saving developer time and reducing
mistakes. Furthermore, within teams, components libraries improve
collaboration between developers.
Defining your first component
Once you have included Modulo and activated it, you can define your first
custom component. Right now, we'll do that by "embedding" the
component definition into the script tag that we used to activate Modulo for
simplicity's sake. Later, we'll learn how to split your components into a
separate file and then include that file, which is the preferred way.
Component definitions start with a "Component"
opening tag in the format of
<Component name="HelloWorld">
. Modulo will look for
these tags, defining components for each one it encounters. Every component
definition must specify a name, conventionally in UpperCamelCase
.
This is just a convention when writing code: Technically HTML tag names are all
case insensitive, and so while inspecting the DOM, browsers typically display
them in all-lowercase
, removing any capitalization.
Once defined, you can use a component by referring to it's name as though it
were a plain HTML tag. Components can go anywhere that plain HTML tags can go,
and can be styled with CSS the same way as well. In other words, creating a
component is like creating a brand-new type of HTML tag that can be used
anywhere, just like the original HTML tags of <div>
,
<a>
, etc.
Unlike plain HTML tags, you must use a dash
(-
) when referring to a component. This is a rule of the HTML5
Custom Components standard, which Modulo is based upon.
Modulo's default behavior is to prefix custom components with an
x-
. So, if a component is defined like
<Component name="HelloWorld">
, then it can be
referenced elsewhere like
<x-HelloWorld></x-HelloWorld>
.
To quickly summarize: Components are reusable bits of HTML, JS, and CSS
code, and must be defined within a tag like
<Component name="HelloWorld">
, and then this definition
can be embedded in an HTML page within a script tag like
<script Modulo src="https://unpkg.com/mdu.js">
.
Okay, enough talk, let's actually try this out!
Try it now
- Open up an HTML file in your preferred text editor. It's okay
to start from scratch, or use an existing project.
- Copy & paste in the following code:
- Ensure that the HTML file is opened in your preferred, modern web
browser (such as Firefox or Chrome) as well.
- Refresh your web browser to view the results.
Adding component "slots"
The origin of slots Slots are a feature of the
"shadow DOM", a new-ish feature of web browsers. Modulo replicates the same
behavior of these "shadow" slots, making slots even easier to use without
JavaScript.
As we explored in the last section, components are "define once,
re-use many times" bits of code. Often, it's useful for a component to "wrap
around" other HTML, or contain other HTML. For example, a stylized button
component might wrap around text, or a stylish "modal dialog" component would
wrap around paragraphs and other arbitrary HTML content. You can thus imagine
the button or modal in these examples as having "empty spots" or slots
where this content would go. That is to say, the component is a sort of "empty
picture frame", and the web developer using the component would be able to
"slide content" into the frame's empty slot.
Slots allow there to be "empty spots" in your HTML that proceed to
get filled by arbitrary content supplied when your component is used. Adding a
slot is as simple as including a <slot></slot>
HTML
element in your component's Template definition.
Here's an example that "wraps" a slot inside a div with a CSS class of
"picture-frame":
<div class="picture-frame">
<slot></slot>
</div>
To fill up a slot with HTML content, add the content between the
opening and closing tags of your HTML element. Here's an example that might go
with the above example:
<x-PictureFrame>
<p>My cat:</p>
<img src="./cat.jpg" />
</x-PictureFrame>
Try it now
- Resume editing the HTML file you were working on in the previous
"TRY IT NOW" section.
- Time to add a slot! Let's make our "HelloWorld" component be ready
to have a customized greeting. Edit your embedded component to look
like this:
- Now, let's fill the slot! Edit your usage to include text or even
other HTML between your
x-HelloWorld
opening and closing
tags:
#
2. Component Parts
The central concept to Modulo is that of Component Parts.
Because it is so central, saying Component Parts over and over gets
tiresome, so in this documentation and the source code it's typically shortened
to CParts.
CParts: The Musical Think of CParts like the
cast and crew of a musical. Each are assigned to a different task—some
are more flashy and visible, others being stage-hands working behind the
scenes—but they all work together to put on the same
show!
All component definitions consist of some number of CParts. Thus, a
component definition is really just a collection of CPart definitions.
"Under the hood" of your component, each CPart will have a different role
to contribute to the functionality of your component.
Let's start with the two most basic CParts:
-
Template -
<Template>
Templates are where you put any arbitrary HTML code that you
want your component to contain. For now, we'll just include some
unchanging HTML. Later, we'll learn how to use "templating
language" to control what HTML is produced in what
circumstance.
-
Style -
<Style>
Just like the <style>
tag in HTML, the
Style CPart allows us to write CSS for our
component. CSS written here will be automatically prefixed so that
it will only apply to your component and any HTML generated by the
Template CPart.
Where to put CSS Instead of a
Style CPart, you can always link a global CSS file the regular way
to style your components. However, many developers prefer the
simplicity of keeping everything in one place, e.g. the CSS with
the component definition that it styles.
Like Component naming, most CParts are technically case-insensitive (e.g.
"<style>
" will work the same as
"<Style>
"). However, it's important you follow the
convention of making the CPart names start with a capital letter, such that you
can easily distinguish them from plain HTML tags.
Throughout Modulo documentation, there are little code editors, like below.
These allow you to immediately practice new concepts learned. For simplicity,
the top and bottom of the component definition code is omitted. Instead, these
sample code editors only focus on the CPart definitions within.
Try it now
Edit the component definition on the left, and click RUN to see the
results on the right!
- Practice modifying the Template CPart
(
<Template>
) to see how that affects the
output preview on the right
- Practice modifying the Style CPart
(
<Style>
) to add or modify CSS
- Practice incorporating these CParts into your own components on
a real page by copying the code here and pasting it within your
component definition (that is, the one that you created in the
previous part of this tutorial)
Hello Modulo World!
Any HTML can be here!
#
3. Loading from files
Why use library files?
The appeal of using a separate CSS file is sharing style across pages, as the
<link>
tag, which lets multiple HTML files share the same
CSS. The same rationale applies here: Components are "write once, use
everywhere", so the way we get access to them "everywhere" is by including them
into each file that needs to use them. Finally, by putting your components in a
separate file, you avoid some awkward HTML syntax issues, since it's impossible
to "nest" <script>
tags.
Up until now, we have practiced with a component embedded on the same page
that it is used. This is not recommended. Instead, you should put your
components in a separate component library HTML file, and then
importing them into each HTML file that needs them.
This can be done by simply copying the insides of the
<script Modulo ...
tag, and pasting them into a new
file. Then, you must include a special -src
attribute to specify
the new file. See below:
<script Modulo
src="https://unpkg.com/mdu.js"
-src="/libraries/my_components.html"
></script>
This "4-liner" can now be included in any of your HTML files to import
whatever components you have defined in
/libraries/my_components.html
.
This allows you to share the same components across multiple pages.
Try it now
It's time to "promote" your beginner embedded component into a
full-fledged loaded component!
Warning: This step of the tutorial, where we load from
separate libraries, might not work unless you have a server
running. This is because if you just double-click on an HTML file, it opens
in the browser with the file://
protocol, which, as a security
precaution, doesn't support loading any subsequent files. Consult your IDE
on how to run a development server (e.g. VS Code seems to have a popular
3rd party add-on:
Live
Server for VSCode). Consider saving this step for later if you do not
have such a server ready.
- Optional: Create a new "libraries" directory to house your
component library files.
- Create a new file for your component library within your
libraries directory (or elsewhere). You could call it, for
example,
my-component-lib.html
- Copy your existing
HelloWorld
component definition
from your main HTML file into this new file, and then delete it
from your main HTML file. If done correctly, your new component library
file (e.g. my-component-lib.html
) should contain the
following text (note the lack of
<script Modulo ...
etc):
- Add a
-src=
attribute to your Modulo script tag,
pointing toward a relative path to your new component library file.
For example, if you named everything based on the above suggestions, it
would look like this:
- Refresh the web browser to view the results. If done correctly,
nothing should change. To confirm it's working, try editing your
component in the library file and refresh to see the results.
- Now, you can simply "drop in" these 4 lines of
script
tag on multiple HTML pages, and they will be all you need to import
and share the same set of components between pages!
Bonus Challenge:
Try practicing with multiple "main HTML" files sharing the same
component library. Also, if you used the example name, consider renaming
your component library. Consider naming it something that is relevant to
you, e.g. "ecommerce-website-components" or something, whatever you think
is a good name based on what you are working on.
Splitting off larger CParts
A convenient feature of Modulo is the ability to "split off" CParts
(individually) into separate files. This allows you to work with dedicated
.html
and .css
files separately, instead of embedding
everything into a HTML file.
In the previous section, -src=
was used on a
<script Modulo ...
tag to move components into a
separate file. Now, we'll see how this same attribute can be used on individual
Componnt Parts.
Using -src=
To "split off" a long CPart into a separate file, begin by cutting out the
contents of a CPart, and pasting it in a new file, and then save this new file
in the same directory as your component library. Finally, to re-include it, add a
-src=
attribute to CPart, just as we did with the
Modulo
tag. Note the dash (-
) before it. This is what
distinguishes it from an ordinary src
attribute, which Modulo will
ignore. By default, -src=
is supported by any CPart that uses it's
contents, meaning Template and Style are the only two that
we've learned so far that support it.
For example, you can split off a Template into it's own separate
file, as such:
<Template
-src="./my-file-name.html"
></Template>
Similarly, you can split off a Style as well:
<Style
-src="./some/other/path.css"
></Style>
The rules for -src=
relative paths are similar to HTML's rules:
Any URI path can be specified, and use a dot (.
) to specify a path
relative to the current HTML file (e.g. the Component library file).
The behavior is the exact same as if you had included the text in the same
file, meaning this feature is only intended to be used when a component library
gets too long and difficult to edit. In that case, conventional usage is to
start splitting off larger CParts into their own files, until the HTML library
file itself is just tie-ing everything together.
Part 1: Summary
In this tutorial, we learned what a Component is, and how to
define one, about what CParts are, and two important CParts
(Template, for HTML, and Style, for CSS), and finally how
to keep our components in a component library and then load that library
into different HTML files. At this point, you can already start getting
useful results from using Modulo, since even without JavaScript usage we
are already defining simple components that can help us re-use HTML code
between different pages.
Key terms
- Component - A discrete, re-usable bit of code, typically
used to show a graphical UI element (eg a button, or a rich-text area).
Components can also use other components (eg a form component might contain
both of the above as child components).
- Component Part, or CPart - Each component
consists of a "bag" or "bundle" of CParts, each CPart being a "pluggable"
module that supplies different functionality for that component. Every
component is defined as a collection of CParts (e.g. HTML Template,
or Style tag).
- customElement - The term used for a custom HTML5 web
component, which is the underlying technology that Modulo is a thin wrapper
over. They all have dashes (
-
) in the name.
- slot - A placeholder for content to be inserted when a
component is used. Useful for writing components that "wrap around" other
content.
- -src= - A special attribute that allows content in Modulo
to be loaded from separate files, making it easier to manage as projects grow.
In the subsequent tutorials we will go deeper: Explore the full capabilities
of Templates, allow flexible and composable components with Props CPart, create
custom behavior with Script CParts, and finally create forms and interactive,
changing components with the State CPart.
Part 2: Props, Templating, and Building »