You give it HTML and it gives back an image!
Parses HTML/CSS, fetches nested resources, renders an image. No browser, no fuss.
Perfect for OpenGraph images - stop losing clicks to boring links by adding a rich image preview that showcases your content.
Quickstart
Command Line
gem install himg
himg screenshot path/to/your.html screenshot.png
himg screenshot https://himg.jamedjo.co.uk himg.png --width=1024 --verbose --no-truncate
echo '<h1>Hello Image</h1>' | himg screenshot --stdin output.png
Ruby
png = Himg.render("<!DOCTYPE html><body style='background:blue;'></body>")
File.open("blue.png", "wb"){|f| f.write(png) }
png = Himg.render("<!DOCTYPE html><h1>Snapshot</h1>", width: 89, height: 5, truncate: false)
File.open("dynamic_height.png", "wb"){|f| f.write(png) }
Rails
Simply add a show.himg.erb
!
<div><%= @username %></div>
OpenGraph Meta Tags
OpenGraph tags let messenger apps and social media sites know to use your generated image as a thumbnail card for your website.
<meta property="og:title" content="<%= @user.username %>" />
<meta property="og:description" content="<%= @user.tagline %>" />
<meta property="og:image" content="<%= user_url(@user.username, format: :png) %>" />
Usage
Install the gem and add to the application's Gemfile by executing:
bundle add himg
Configuration
Option | Description | Type | Default |
---|---|---|---|
width | Sets the width of the rendered content. | integer | 720 |
height | Sets the desired height of the rendered output. | integer | 405 |
truncate | Keeps the image height fixed instead of expanding to include the full page | bool | true |
verbose | Enables detailed logging for debugging and profiling. | bool | false |
base_url | Where relative paths are relative to for linked resources (stylesheets, images, fonts, etc) | string | nil |
disable_fetch | Disables fetching linked resources from disk and network | bool | false |
fetch_timeout | Timeout in seconds for fetching resources | float | 10.0 |
gpu | Use GPU renderer instead of CPU renderer | bool | false |
http_headers | Headers sent when the CLI fetches the SOURCE HTML (CLI only) | hash | nil |
stdin | Read HTML content from stdin instead of a file (CLI only) | bool | false |
Passing options to a Rails view template
Options can be set at a controller level using the himg_config
helper method:
class UsersController < ActionController::Base
himg_config(verbose: true)
end
These can be overridden at a view level:
class UsersController < ActionController::Base
def show
himg_config(width: params[:w]) if params[:w]
@user = User.new
end
Rails manual render
If you prefer you could also use render himg: "<div>My Data</div>"
instead, but should be careful with untrusted input if constructing HTML manually.
Options can then be passed directly to the manual render:
render himg: '<!DOCTYPE html>', truncate: false
Alternatively you can pass in options which have been set with himg_config
:
render himg: '<!DOCTYPE html>', config: himg_config
Rails respond_to
To be explicit in the controller you can also use respond_to
style:
respond_to do |format|
format.html
format.himg
end
You can also use this combined with a manual render:
respond_to do |format|
format.html
format.himg { render himg: '<h1 style="text-align: center;">Recent Users</h1>' }
format.png { render himg: '<div>For .png URLs</div>' }
end
Supported HTML and CSS
Himg supports a large subset of the HTML and CSS you'd need to get by, but not all elements or properties are supported.
For a full list, see our snapshot of the blitz.is status page.
If something you'd like supported is missing and is available upstream on Blitz, please open an issue.
HTML | Status |
---|---|
Generic HTML5 elements |
✅ Supported |
<style> |
✅ Supported |
<link rel="stylesheet"> |
✅ Supported |
<link rel="icon"> |
❌ Not supported |
<img src=""> |
✅ Supported |
<img srcset=""> |
❌ Not supported |
<picture> |
❌ Not supported |
<svg> |
⚠️ Partial support |
<h1>-<h6> |
✅ Supported |
<ul>/<ol> |
✅ Supported |
<i>/<em> |
✅ Supported |
<b>/<strong> |
✅ Supported |
<u> |
✅ Supported |
<center> |
✅ Supported |
<pre>/<blockquote> |
✅ Supported |
<a> |
✅ Supported |
<br> |
✅ Supported |
<hr> |
❌ Not supported |
<details>/<summary> |
❌ Not supported |
<table> |
⚠️ Partial support |
Form Controls |
⚠️ Partial support |
CSS | Status |
---|---|
display:inline, display:block, display:inline-block |
✅ Supported |
display:none |
✅ Supported |
display:flex |
✅ Supported |
display:grid |
⚠️ Partial support |
display:table |
⚠️ Partial support |
display:contents |
❌ Not supported |
position:relative, position:absolute |
✅ Supported |
position:static, position:fixed, position:sticky |
❌ Not supported |
overflow |
⚠️ Partial support |
z-index |
⚠️ Partial support |
box-sizing |
✅ Supported |
float |
❌ Not supported |
content (::before / ::after) |
⚠️ Partial support |
opacity, visibility |
✅ Supported |
width, height |
✅ Supported |
min-width, max-width, min-height, max-height |
✅ Supported |
padding, margin, gap |
✅ Supported |
border |
⚠️ Partial support |
@font-face, font-size, font-family |
✅ Supported |
font-weight, font-style, font-stretch |
✅ Supported |
font-display, font-variant, font-feature-settings |
❌ Not supported |
color, text-align, line-height, text-decoration |
✅ Supported |
letter-spacing, overlap-wrap, word-wrap, word-break |
✅ Supported |
vertical-align, text-transform, text-overflow |
❌ Not supported |
border |
⚠️ Partial support |
background-color, background-image |
✅ Supported |
background-size, background-position |
✅ Supported |
background-repeat, background-clip, background-origin |
✅ Supported |
background-attachment |
❌ Not supported |
box-shadow |
✅ Supported |
filter |
❌ Not supported |
How it works
No browser, just basics!
Himg calls through to the amazing blitz library, which uses Stylo to parse the CSS, servo/html5ever to parse the HTML, fetches network resources, builds a scene graph and hands over to vello to render an image.
Interaction between Ruby & Rust is done with the help of magnus
, rb_sys
and lots of glue code from the oxidize-rb
team.
To play nicely with Rails a template handler is registered, which Rails' default_render
method automatically calls when the corresponding view is found. This can be show.himg
for a static image, or show.himg.erb
to use variables from the controller. Additionally a Renderer is available with render himg: 'content'
in case a view template is not needed.
CAVEATS
- This is pre-alpha software, don't expect it to work perfectly yet.
- Performance needs tuning. Both in the underlying Blitz library and how data is passed between Rust and Ruby
- Network requests can be made: don't use this library with untrusted inputs. Use
disable_fetch
if you don't need to fetch any resources. - file:// URLs are resolved: this could expose files on your computer. Use
disable_fetch
if you don't need to fetch any resources.
Development
- Run
bin/setup
to install dependencies. - Run
rake spec
to run the tests with the default development setup - Run
appraisal rake spec
to run tests against different versions of rails and to confirm that the gem works in a plain ruby environment - Run
bin/console
for an interactive prompt that will allow you to experiment. - Run
RAILS_ENV=development bundle exec spec/dummy/dummy_rails server
to check the dummy app.
- http://localhost:3000/users/jamedjo.png will display an opengraph compatible png
- http://localhost:3000/users/jamedjo.himg will also render the same png
- http://localhost:3000/users/jamedjo will render an HTML page with opengraph meta tags
- To install this gem onto your local machine, run
bundle exec rake install
. - To simulate a headless server environment without a GPU, use
WGPU_BACKEND=empty bundle exec rspec
- To profile performance with flamegraphs, run
bin/profile spec/fixtures/profile_test.html
Run cargo example directly generate image in Rust
bundle exec cargo run --example file
bundle exec cargo run --example file -- path/to/file.html
Releases
To release a new version:
- Run
rake bump:patch
to update the version numbers inversion.rb
andext/himg/Cargo.toml
. - Run
bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the.gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/jamedjo/himg.
License
Copyright (c) 2025 James Edwards-Jones
This project is dual licenced under both the MIT and Apache 2.0 terms.
See: MIT License and APACHE 2.0 License