Image
UI::ImageAn image with consistent sizing and corner radius.
# VelvetKit
## Image (`UI::Image`)
An image with consistent sizing and corner radius.
Add it: `bin/rails generate velvetkit:add image`
### Arguments
```ruby
UI::Image.new(src:, rounded: :sm, width: nil, height: nil, alt: nil, loading: :lazy, class: nil, **html_attrs)
```
### Notes
UI::Image — asset-backed <img> with radius tokens and lazy loading.
Replaces Velvet::Image, which wrapped every image in a Velvet::Box and passed
`width:`/`height:` to that wrapper as inline styles — so the div was sized and
the image itself was not. Here the dimensions land on the <img>.
Usage:
<%= render(UI::Image.new(src: "logo.png", rounded: :lg, width: "100px")) %>
### Example: Radii
```erb
<div class="flex flex-wrap items-end gap-6">
<% %i[none sm md lg xl full].each do |r| %>
<div class="flex flex-col items-center gap-2">
<%= render(UI::Image.new(src: "/icon.png", rounded: r, width: "48px", height: "48px")) %>
<span class="text-xs text-muted-foreground"><%= r %></span>
</div>
<% end %>
</div>
```
### Example: Sizing
```erb
<%# Dimensions land on the <img> itself, not on a wrapper. %>
<div class="flex flex-wrap items-end gap-6">
<% ["48px", "96px", "160px"].each do |w| %>
<div class="flex flex-col items-center gap-2">
<%= render(UI::Image.new(src: "/icon.png", rounded: :md, width: w)) %>
<span class="text-xs text-muted-foreground">width: <%= w %></span>
</div>
<% end %>
</div>
```
bin/rails generate velvetkit:add image
- Also adds
- Nothing else
- Stimulus
- None, it's server-rendered
- Installs
- Nothing
Examples
Radii
radii.html.erb
<div class="flex flex-wrap items-end gap-6">
<% %i[none sm md lg xl full].each do |r| %>
<div class="flex flex-col items-center gap-2">
<%= render(UI::Image.new(src: "/icon.png", rounded: r, width: "48px", height: "48px")) %>
<span class="text-xs text-muted-foreground"><%= r %></span>
</div>
<% end %>
</div>
Sizing
sizing.html.erb
<%# Dimensions land on the <img> itself, not on a wrapper. %>
<div class="flex flex-wrap items-end gap-6">
<% ["48px", "96px", "160px"].each do |w| %>
<div class="flex flex-col items-center gap-2">
<%= render(UI::Image.new(src: "/icon.png", rounded: :md, width: w)) %>
<span class="text-xs text-muted-foreground">width: <%= w %></span>
</div>
<% end %>
</div>
API
Arguments
UI::Image.new(src:, rounded: :sm, width: nil, height: nil, alt: nil, loading: :lazy, class: nil, **html_attrs)
Notes
UI::Image — asset-backed <img> with radius tokens and lazy loading.
Replaces Velvet::Image, which wrapped every image in a Velvet::Box and passed
`width:`/`height:` to that wrapper as inline styles — so the div was sized and
the image itself was not. Here the dimensions land on the <img>.
Usage:
<%= render(UI::Image.new(src: "logo.png", rounded: :lg, width: "100px")) %>