Marko Fundamentals
Tldr
- Marko builds on top of HTML, enabling components and JavaScript-based interpolation
Marko is designed to feel familiar if you know HTML, while making it easy to build dynamic, interactive websites. Let's walk through the core concepts.
Templates are HTML
Nearly any valid HTML is also valid Marko code. We can start with regular HTML and gradually add features as needed.
<h1>My Blog</h1>
<nav>
<a href="/about">
About
</a>
<a href="/contact">
Contact
</a>
</nav>
h1 -- My Blog
nav
a href="/about" -- About
a href="/contact" -- Contact
<h1>My Blog</h1>
<nav>
<a href="/about">
About
</a>
<a href="/contact">
Contact
</a>
</nav>
h1 -- My Blog
nav
a href="/about" -- About
a href="/contact" -- Contact
Dynamic Content
Tag content in Marko is similar to template literals in JavaScript, so dynamic text can be added with interpolated ${expressions}
<p>Today is ${new Date().toDateString()}</p>
<p>Random number: ${Math.floor(Math.random() * 100)}</p>
p -- Today is ${new Date().toDateString()}
p -- Random number: ${Math.floor(Math.random() * 100)}
<p>Today is ${new Date().toDateString()}</p>
<p>Random number: ${Math.floor(Math.random() * 100)}</p>
p -- Today is ${new Date().toDateString()}
p -- Random number: ${Math.floor(Math.random() * 100)}
Components
To reuse code, we can move it into a separate file. Each .marko
file is a component that can be used like an HTML tag.
<div>
<h3>Alice</h3>
<p>Designer</p>
<p>Joined 2023</p>
</div>
div
h3 -- Alice
p -- Designer
p -- Joined 2023
<div>
<h3>Alice</h3>
<p>Designer</p>
<p>Joined 2023</p>
</div>
div
h3 -- Alice
p -- Designer
p -- Joined 2023
This <card>
component can now be used anywhere in the page:
<h1>Our Team</h1>
<card/>
<card/>
<card/>
h1 -- Our Team
card
card
card
<h1>Our Team</h1>
<card/>
<card/>
<card/>
h1 -- Our Team
card
card
card
Note
Components in the tags/
directory are automatically discovered. Learn more about tag discovery in our reference docs.
Passing Data to Components
Attributes on custom components are available through a special object called input
.
<div>
<h3>${input.name}</h3>
<p>${input.role}</p>
<p>Joined ${input.year}</p>
</div>
div
h3 -- ${input.name}
p -- ${input.role}
p -- Joined ${input.year}
export interface Input {
name: string;
role: string;
year: number;
}
<div>
<h3>${input.name}</h3>
<p>${input.role}</p>
<p>Joined ${input.year}</p>
</div>
export interface Input {
name: string;
role: string;
year: number;
}
div
h3 -- ${input.name}
p -- ${input.role}
p -- Joined ${input.year}
Now we can pass different data to each instance of card
:
<h1>Our Team</h1>
<card name="Alice" role="Designer" year=2023/>
<card name="Bob" role="Developer" year=2024/>
<card name="Charlie" role="Product Manager" year=2022/>
h1 -- Our Team
card name="Alice" role="Designer" year=2023
card name="Bob" role="Developer" year=2024
card name="Charlie" role="Product Manager" year=2022
<h1>Our Team</h1>
<card name="Alice" role="Designer" year=2023/>
<card name="Bob" role="Developer" year=2024/>
<card name="Charlie" role="Product Manager" year=2022/>
h1 -- Our Team
card name="Alice" role="Designer" year=2023
card name="Bob" role="Developer" year=2024
card name="Charlie" role="Product Manager" year=2022
Tip
In Marko, attribute values are JavaScript expressions. This means they're not limited to just strings and numbers:
<card name="You!" role=input.role joinDate=new Date().getFullYear() + 1/>
card name="You!" role=input.role joinDate=new Date().getFullYear() + 1
<card name="You!" role=input.role joinDate=new Date().getFullYear() + 1/>
card name="You!" role=input.role joinDate=new Date().getFullYear() + 1
Conditionals
We can use conditional tags (<if>
and <else>
) to show or hide content based on conditions.
<div>
<h3>${input.name}</h3>
<p>$${input.price}</p>
<if=input.stock>
<button>Add to Cart</button>
</if>
<else>
<button disabled>
Out of Stock
</button>
</else>
</div>
div
h3 -- ${input.name}
p -- $${input.price}
if=input.stock
button -- Add to Cart
else
button disabled -- Out of Stock
<div>
<h3>${input.name}</h3>
<p>$${input.price}</p>
<if=input.stock>
<button>Add to Cart</button>
</if>
<else>
<button disabled>
Out of Stock
</button>
</else>
</div>
div
h3 -- ${input.name}
p -- $${input.price}
if=input.stock
button -- Add to Cart
else
button disabled -- Out of Stock
Now we can show different states based on the product data:
<product name="T-Shirt" price=25 stock=10/>
<product name="Hoodie" price=45 stock=0/>
<product name="Hat" price=15 stock=5/>
product name="T-Shirt" price=25 stock=10
product name="Hoodie" price=45 stock=0
product name="Hat" price=15 stock=5
<product name="T-Shirt" price=25 stock=10/>
<product name="Hoodie" price=45 stock=0/>
<product name="Hat" price=15 stock=5/>
product name="T-Shirt" price=25 stock=10
product name="Hoodie" price=45 stock=0
product name="Hat" price=15 stock=5
Next Steps
Contributors
Helpful? You can thank these awesome people! You can also edit this doc if you see any issues or want to improve it.