RmlUi - The HTML/CSS User Interface library evolved

RmlUi - The HTML/CSS User Interface Library Evolved


RmlUi - now with added boosters taking control of the rocket, targeting your games and applications.

Chat on Gitter Build Build status Build Status

RmlUi is the C++ user interface package based on the HTML and CSS standards, designed as a complete solution for any project's interface needs. It is a fork of the libRocket project, introducing new features, bug fixes, and performance improvements.

RmlUi uses the time-tested open standards XHTML1 and CSS2 while borrowing features from HTML5 and CSS3, and extends them with features suited towards real-time applications. Because of this, you don't have to learn a whole new proprietary technology like other libraries in this space. Please have a look at the supported RCSS properties and RML elements.

Documentation is located at https://mikke89.github.io/RmlUiDoc/

Note: RmlUi 4.0 currently in development is a restructuring of RmlUi 3.x. This includes changes to the namespaces, plugins, and include headers. Take a look at the changelog for a summary of changes and an upgrade guide.


  • Cross platform architecture: Windows, macOS, Linux, iOS, etc.
  • Dynamic layout system.
  • Full animation and transform support.
  • Efficient application-wide styling, with a custom-built templating engine.
  • Fully featured control set: buttons, sliders, drop-downs, etc.
  • Runtime visual debugging suite.


  • Abstracted interfaces for plugging in to any game engine.
  • Decorator engine allowing custom application-specific effects that can be applied to any element.
  • Generic event system that binds seamlessly into existing projects.
  • Easily integrated and extensible with Lua scripting.


  • The user controls their own update loop, calling into RmlUi as desired.
  • The library strictly runs as a result of calls to its API, never in the background.
  • Input handling and rendering is performed by the user.
  • The library generates vertices, indices, and textures for the user to render how they like.
  • File handling and the font engine can optionally be fully replaced by the user.

Integrating RmlUi

Here are the general steps to integrate the library into a C++ application, have a look at the documentation for details.

  1. Build RmlUi using CMake and your favorite compiler, or fetch the Windows library binaries.
  2. Link it up to your application.
  3. Implement the abstract system interface and render interface.
  4. Initialize RmlUi with the interfaces, create a context, provide font files, and load a document.
  5. Call into the context's update and render methods in a loop, and submit input events.
  6. Compile and run!

Several samples demonstrate everything from basic integration to more complex use of the library, feel free to have a look for inspiration.


In addition, a C++14 compatible compiler is required.

Example: Basic document

In this example a document is created using a templated window. The template is optional but can aid in achieving a consistent look by sharing it between multiple documents.



	<title>Hello world</title>
	<link type="text/template" href="window.rml" />
			width: 200px;
			height: 100px;
			margin: auto;
<body template="window">
	Hello world!

Window template


<template name="window" content="content">
	<link type="text/rcss" href="rml.rcss"/>
	<link type="text/rcss" href="window.rcss"/>
	<div id="title_header">RmlUi</div>
	<div id="content"/>

No styles are defined internally, thus rml.rcss can be included for styling the standard elements.

Style sheet


	font-family: Delicious;
	font-weight: normal;
	font-style: normal;
	font-size: 15px;
	color: #6f42c1;
	background: #f6f8fa;
	text-align: center;
	padding: 2em 3em;
	border: 2px #ccc;

	color: #9a42c5;
	font-size: 1.5em;
	font-weight: bold;
	padding-bottom: 1em;

Rendered output

Hello world document


Game interface Game interface from the 'invader' sample

Game menu Game menu

Form controls Form controls from the 'demo' sample

Sandbox Sandbox from the 'demo' sample, try it yourself!

Transitions on mouse hover (entirely in RCSS)

Animated transforms (entirely in RCSS)

Lottie animation
Vector animations with the Lottie plugin

See the full gallery for more screenshots and videos of the library in action.


RmlUi is published under the MIT license. The library includes third-party source code and assets with their own licenses, as detailed below.

RmlUi source code and assets

MIT License

Copyright (c) 2008-2014 CodePoint Ltd, Shift Technology Ltd, and contributors
Copyright (c) 2019-2021 The RmlUi Team, and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


Third-party source code included in RmlUi Core

See Include/RmlUi/Core/Containers/LICENSE.txt - all MIT licensed.

Third-party font assets included in RmlUi Debugger

See Source/Debugger/LICENSE.txt - SIL Open Font License.

Additional sample assets (in Samples/)


Libraries included with the test suite (in Tests/Dependencies/)

See Tests/Dependencies/LICENSE.txt.

Additional test suite assets (in Tests/Data/VisualTests/)

See Tests/Data/VisualTests/LICENSE.txt.

  • Proposal for replacing decorator syntax, add sprite sheet support

    Proposal for replacing decorator syntax, add sprite sheet support

    While the work on increasing performance is well underway with great results already, there are some ideas that could improve it further but break some existing things, and possibly reduce some of the generality of the library.

    Specifically, strings are passed and copied everywhere around in the code and need to be looked up in hash tables quite a lot. Especially for properties, events, and possibly pseudoclasses. What I propose instead is to use simple numeric IDs, one specific for each property. Everything would become much simpler then if we disallow custom property names (such as those used by decorators) and events.

    But of course, we're not getting rid of decorators! Instead, I think we can improve them.

    I think it is kind of awkward currently to have to specify the exact subrectangle in a texture right inside the decorator declaration. Instead, I propose first that we enable somehow to define a spritesheet with all subrectangles defining a given sprite in one place. Then we introduce a new property, either decorator or background-image (as in css) which specifies a decorator by combining possibly multiple sprite names from the spritesheet, and comma-separated for multiple decorators.

    E.g. something like this:

    @spritesheet(invader-theme) {
       src: invader-theme.png;
       invader-left: 10px 40px 30px 10px;
    button.invader {
     decorator: tiled-horizontal(invader-left, invader-center, invader-right), image(button-bg);

    One of the nice things is that we could then easily replace the whole spritesheet (1) to change to a different theme, or more importantly, (2) to specify a higher resolution image when the dp unit changes so that the textures are crisp at say 1dp==2px.


  • Moving towards a 3.0 release of RmlUi

    Moving towards a 3.0 release of RmlUi

    I feel like we have a considerable amount of features in the develop branch now, and it's time we merge it with master soon for an official 3.0 release.

    The obvious major thing missing is documentation of all the new features, and we probably need to go through all the existing documentation as a lot of details have been changed. The changelog is quite exstensive, and should serve as a good starting point.

    If there is something you feel should be done before the release of RmlUi 3.0, then let's discuss it here. Also if you find or know of any larger bugs or stability issues, it would be nice to have these resolved before the release.

  • RFC: new font provider interface

    RFC: new font provider interface

    The major difference between stock libRocket and our own fork here https://github.com/Qfusion/libRocket is that the former manages its own library of fonts and glyphs and is closely tied to freetype. Quite often this is an undesired behaviour: bitmap fonts, fonts are managed by the application, etc.

    Related PR: https://github.com/libRocket/libRocket/pull/267/files

    Related commit in our fork: https://github.com/Qfusion/libRocket/commit/c0d15d82128f6e254234adf9e5531042f3d94661

    The downside of our implementation isn't able to handle font effects as it doesn't export rendered glyphs to libRocket.

  • Rename project, libMissile?

    Rename project, libMissile?

    As suggested by @barroto in #2, this fork of libRocket is now quite distinct from the original project. A rename of this work then seems natural.

    Some things that me may consider with this change:

    • Update the original documentation with the new changes
    • Rename the namespace from Rocket to.. Missile?
    • A new logo?
    • Updated templates?

    What do you think? These are just ideas I'm throwing out there, any ideas you may have are very welcome.

    I'm not sure how the original documentation was built, but you seem able to assist here, @barroto?

  • ElementDocument::FocusFirstTabElement


    bool FocusFirstTabElement(void) { return FocusNextTabElement(this, true); }

    We use this function to focus on the first "tabbable" element when the document is displayed for the first time, if possible. Make sense for modal dialogs, input forms and such.

    Please consider adding this function to the public API or maybe, as an alternative, a new Focus flag with similar functionality.

  • Remove all manual reference counting

    Remove all manual reference counting

    And replace them with unique_ptr, or shared_ptr where strictly necessary. E.g. elements should uniquely own their children. Replace AddChild with CreateChild so users don't have to move them on every element creation.

    All use of raw pointers should then denote a non-owning pointer.

  • Pack assets directory to binnary resource

    Pack assets directory to binnary resource

    Is it possible to pack assets directory to binnary resource?

    What Sciter(https://sciter.com/) did:

    Run commond packfolder.exe ui resources.cpp -v "resources" and then generate code like this:

    const unsigned char resources[] = {

    What Electron(https://github.com/electron/electron) and yue(https://github.com/yue/yue) did:

    Pack assets directory to a zip(like) file without compression but support random access. See:https://github.com/electron/asar

  • Add ability for user to override container types

    Add ability for user to override container types

    This is an implementation of my ideas raised in #107. Please review and comment.

    It was nice to find out that lua integration did not require any changes whatsoever. Yay!

    Few unrelated observations:

    • Project should adopt .editorconfig. I had to restore bunch of trailing spaces to avoid extra noise in commits. Editor was eager to get rid of them. This would also configure editors to use tabs.
    • Project should adopt .gitattributes and normalize line endings. Most files use \n while some use \r\n. This puts us in a position where one line change may flag entire file as changed only because editor changed line endings.
    • Changes to CMakeLists.txt are not proper, but then again entire build script is in a state where it just can not be fixed, but should be rewritten instead. I might do it in the future (no promises).
  • Media queries

    Media queries

    This is a big one.

    This PR adds support for basic media queries in RCSS.

    Usage & Features

    • RCSS media-blocks to apply properties conditional to context properties:
      • viewport width & height given in pixels, supports range (min-/max-)
      • resolution, aka dpi (using the density_independent_pixel_ratio value), supports range (min-/max-)
      • aspect ratio, using ratio notation like 16/9, internally using it as a float, supports range (min-/max-)
      • orientation "landscape" / "portrait", comparing viewport width against height
    • Creating composite queries using "and" operator

    Example usage:

    div {
    	height: 48px;
    	width: 48px;
    @media (min-width: 640px) {
    	div {
    		height: 32px;
    		width: 32px;
    @media (orientation: landscape) and (min-resolution: 90dpi) {
    	div {
    		height: 32px;
    		width: 32px;
    @media (max-aspect-ratio: 4/3) {
    	div {
    		height: 64px;
    		width: 64px;

    I've tried to adhere as closely as possible to the early CSS media query standards, by for instance inforcing fixed units like dpi for resolution, and pixels for width & height and reusing the CSS names for the various properties. The CSS feature of media distinction like "screen" etc. does not really apply in RCSS, therefore it was omitted. The current approach matches media blocks with an all or nothing approach, since only conjunctive chaining ("and") is allowed.


    In order to assemble the correct style sheet for a given context configuration, a new top-level class above StyleSheet was introduced: the StyleSheetContainer. It maps a PropertyDictionary of the query-list properties to the contained sub-stylesheet.

    A function UpdateMediaFeatures creates a new combined StyleSheet and stores it inside the container, giving external access through a non-owning pointer.

    For parsing, new parsers needed to be introduced, namely for the aspect ratio notation, and others for the unit enforcing.

    The style sheet parser received a new parsing method with its own state machine parsing the custom syntax of the media query list

    The document re-compiles the stylesheet when it detects a context property change.

    A unit test suite checking all properties is provided.

  • GetOwnerDocument returns null in InstanceEventListener

    GetOwnerDocument returns null in InstanceEventListener

    I want to know which document it comes from when the event listener is initialized. But at this time the element has not been added to the document, so GetOwnerDocument returns null. I noticed that InstanceElement has a parameter, Element parent. Does this mean that the element already has an owner?

  • font-charset


    The font interface libRocket as a whole relies on "font-charset". If this applies to RmlUi is there a possibility of removing font-charset workaround in order to simply generate glyphs as needed or at least let me use my own better font renderer.

    I mostly say this as I want to use emoji and russian and many other languages (depending on user choice).


  • Custom renderer cannot render full text string

    Custom renderer cannot render full text string

    RmlUi cannot render full text string to window as follow. I have no idea about this. Is there anyone know why?


    	<title>Hello world</title>
    	<link type="text/rcss" href="window.rcss"/>
    <body data-model="animals">
    	<p>Hello<span id="world">world</span>1234567890!</p>
    	<p data-if="show_text">The quick brown fox jumps over the lazy {{animal}}.</p>
    	<input type="text" data-value="animal"/>



    • Text RmlUi only render first three characters Rml.
    • Other problems as show in the top image.
  • Building RmlUi from source using Conan's Freetype package

    Building RmlUi from source using Conan's Freetype package

    After struggling for several days on how to do this, I finally found a way to do it and thought it might be useful for anyone else having the same issues as I did.


    In order to use unreleased versions of RmlUi (git) or use versions of RmlUi that haven't been distributed yet in vcpkg or Conan one has to go through the process of building RmlUi from source. While this might seem easy at first, having to download a compiled binary and paste it inside the source tree of a dependency, even if it's ignored by Git, is rather inconvenient. There's no guarantee you'll be able to find a Freetype distribution that matches your requirements (linkage, compiler and ABIs, version, compile options...), specially on Windows where most distributions are only compiled using MSVC, not to mention the fact that you still have to "install" them and how cumbersome it is in Windows.

    For this reason, I followed the official Conan documentation to download Freetype 2.10.4 for Windows, just to find out that the instructions in Conan Center make you use a toolchain file to populate variables instead of using an initial cache script (argument -C <initial-cache-script> when configuring/generating the project). And there's a problem with that logic:

    CMake uses a toolchain of utilities to compile, link libraries and create archives, and other tasks to drive the build. The toolchain utilities available are determined by the languages enabled. In normal builds, CMake automatically determines the toolchain for host builds based on system introspection and defaults. In cross-compiling scenarios, a toolchain file may be specified with information about compiler and utility paths.

    -- CMake toolchains official documentation

    --toolchain <path-to-file>

    Specify the cross compiling toolchain file, equivalent to setting CMAKE_TOOLCHAIN_FILE variable.

    -- cmake CLI official documentation

    -C <initial-cache>

    Pre-load a script to populate the cache.

    When CMake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project. This option may be used to specify a file from which to load cache entries before the first pass through the project's CMake list files. The loaded entries take priority over the project's default values. The given file should be a CMake script containing set() commands that use the CACHE option, not a cache-format file.

    References to CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR within the script evaluate to the top-level source and build tree.

    -- cmake CLI official documentation

    Using toolchain files like this goes against the nature of CMake toolchain files being intended to be used in cross-compilation scenarios, and it's also the reason why I don't like using vcpkg no matter how straightforward it might seem to use. In fact, the method described in Conan Center, which uses the CMake toolchain file, doesn't even work and makes the build process of RmlUi fail due to missing headers.

    Making things worse, due to Conan being in the process of revamping their integration with CMake for their 2.0 release by declaring the older integration methods obsolete and replacing them with new (and as of today, unstable) ones, their documentation about the CMake integration is all over the place and fragmented between their Getting Started guide, the Conan Center instructions and the more in-depth articles from their documentation.

    About the newer Conan generators:

    • CMake is intended to be used only inside a Conan package recipe and not by integrators/users of said packages
    • CMakeToolchain goes against the nature of CMake toolchain files, and as of today it doesn't even work for this case
    • CMakeDeps utilizes CMake package config files instead of Find<package>.cmake modules, which should be the ideal

    However, while using CMakeDeps allows for a successful project configuration and build, the final linking step fails with MSVC error LNK2019 due unresolved external symbols related to Brotli and PNG. Why? Because RmlUi uses find_package(Freetype ...) to find Freetype, which fallbacks to the CMake-provided FindFreetype.cmake module, which somehow enters in conflict with the Freetype distribution from Conan and ends up breaking symbol linking and/or includes for Freetype.

    Because of all of this, and by the means of the official documentation, there's no way to make this work. But reality seems to tell otherwise.

    How to actually do it (for CMake superprojects)

    The goal for this, or at least the one I had when trying to find a way to do it, is to set up CMake in a way that no user intervention neither any kind of dedicated "bootstrap" or "development environment configuration" scripts are needed. Just installing Conan and generating the project or loading the root source folder in an IDE with CMake integration is all that's needed for everything to be properly set up.

    For the sake of respecting the CMake binary directory workflow, all Conan-generated files will go inside the CMake binary directory that you generate. This allows you to keep multiple binary directories with different configurations (target platform, architecture, toolchain, compile flags...) living under your source tree without having problems of one build suddenly trying to link against an incompatible Conan package binary.

    To share configuration settings between people (ex. to set CONAN_PROFILE, compilers, flags...) it is strongly advised to use CMake Presets.

    For this explanation, a minimal reference project will be used with the following structure:

    - rmlui/
    - CMakeLists.txt
    - conanfile.txt
    - main.cpp

    In the file structure, rmlui is folder containing a copy of the RmlUi source code, while main.cpp contains the following:

    #include <iostream>
    #include <RmlUi/Core.h>
    int main(){
        std::cout << "hello world";

    The solution for this issue and how to build RmlUi using Conan's Freetype depends on the version of Conan and the version of CMake:

    CMake <= 3.23

    Conan < 2.0

    In CMake 3.23 and lower, calls to find_package() will default to module mode. If the Conan CMakeDeps generator is used to point CMake to the packages, the RmlUi project will still ignore some of the settings from the Conan configuration files, go with the CMake ones and therefore break the symbol references just like it was told above. To solve this, we need to force CMake to ignore its own find modules and stick to what Conan specifies by making Conan create alternative find modules that supersede the default ones:

    • conanfile.txt

      # This is only necessary if you are using any Conan package in the form of a shared library
      # but its good to have it anyway so you don't have to care about any additional setup if you
      # change your mind about the linking method at a later date
      bin, *.dll -> ./conan_bin # Copies all dll files from packages bin folder to the CMake binary directory
      lib, *.dylib* -> ./conan_bin # Copies all dylib files from packages lib folder to the CMake binary directory
      lib, *.so -> ./conan_bin # Copies all so files from packages lib folder to the CMake binary directory
    • CMakeLists.txt

      # The CMake version that I've used to test this is 3.23, but the real minimal version might be lower
      cmake_minimum_required(VERSION 3.23)
      project(HelloWorld CXX)
      # ------ First, we need to set up the dependencies ------
      # Find Conan
      find_program(conan NAMES "conan" DOC "Conan package manager" REQUIRED)
      # Cache option to set the Conan build profile, which defaults to "default" if not specified by user
      # More info here: https://docs.conan.io/en/1.50/reference/profiles.html
      set(CONAN_PROFILE "default" CACHE STRING "Conan profile to be used when compiling and installing packages.
      In order to avoid issues, the toolchain set in the Conan profile must match the one being used to compile
      the project, or at least the ABIs (ex. clang-cl and MSVC). Failing to do this might result in compilation and/or linkage issues."
      # Add configuration files for the Conan packages inside CMake binary directory
      # Also compiles dependencies if necessary
      execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} --build=missing -pr:b=${CONAN_PROFILE}
      # Add Conan module (find modules) and config file paths so that all CMake projects are
      # able to find the packages they need regardless of the find_package() mode they use
      # The variable isn't present on cache to avoid issues when CMake is re-run over an existing
      # binary directory
      # IMPORTANT: Ensure Freetype is found using the module method by finding it ourselves before
      # any other dependency does so
      # If any other part of the project was to successfully find Freetype using find_package() in
      # config mode, the compilation of RmlUi would break
      find_package(Freetype MODULE)
      # ------ Then, we include the RmlUi CMake project in the build pipeline ------
      # ------ With everything set up, all that's left is to declare our own target ------
      # Declare our executable
      add_executable(HelloWorld main.cpp)
      # Link our executable against RmlUi
      # Since we have included the RmlUi CMake project itself in our build pipeline,
      # we now use its actual CMake target name to reference it in our project
      target_link_libraries(HelloWorld PRIVATE RmlCore)
      # Add step to copy Conan DLLs into the same directory as our compiled executable
      # right after a build has been completed
      # This is only necessary if you are using any Conan package in the form of a shared library
      # but its good to have it anyway so you don't have to care about any additional setup if you
      # change your mind about the linking method at a later date
      add_custom_command(TARGET HelloWorld POST_BUILD
          # Create source directory first so copy_directory doesn't fail if it doesn't exist
          COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/conan_bin
          COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/conan_bin $<TARGET_FILE_DIR:HelloWorld>

    To configure and build:

    1. Check the contents of the default Conan build profile for your platform using:

      conan profile show default

      Which in Windows with Visual Studio 2022 installed should result in:

      Configuration for profile default:
      compiler=Visual Studio
    2. Decide whether or not the default profile meets your requirements:

      • If the default profile does meet your requirements, you don't need to do anything about it. CMake will automatically choose it for you.
      • If the default profile does not meet your requirements, create a new one using the conventions specified in the Conan reference and Conan profiles. Remember to pass -DCONAN_PROFILE=<absoulte_or_relative_to_the_cmake_binary_dir_path_to_profile> to CMake when configuring/generating the project for Conan to use your new profile file.
    3. Configure the CMake project or load it in an IDE with CMake integration and compile it

    Conan >= 2.0

    In Conan 2.0, due to the deprecation of the cmake_find_package and cmake_find_package_multi it won't be possible to integrate Freetype from Conan into the CMake project using them (or at least it won't be the "right" way to do it anymore) and I don't know if using the CMakeToolchain and CMakeDeps will end up working with RmlUi anyway.

    Something that might help is CMAKE_FIND_PACKAGE_REDIRECTS_DIR from CMake 3.24, which will allow to redirect all calls of find_package() use a config file if present in this directory before anything else, even if the call for find_package() enforces module mode.

    The CLI of Conan 2.0 will also enforce build profiles for both host and build, which will make the

    I'll update this when I get to try the stable versions of both CMake 3.24 and Conan 2.0.

    CMake >= 3.24

    CMake 3.24 introduces Dependency Providers, which should allow package managers like Conan and vcpkg to integrate more tightly with CMake. Due to the release of CMake 3.24 being way closer in time than the release of Conan 2.0, we might seem heavy overhauls to the integration between CMake and Conan before the release of Conan 2.0.

    If you use CMake 3.24 with Conan < 2.0, the method for CMake 3.23 and Conan < 2.0 should work just fine.

    However for the case of Conan >= 2.0 it's still uncertain whether it will work or not. But thanks to the addition of the CMAKE_FIND_PACKAGE_REDIRECTS_DIR variable, it might be possible to completely forget about CMake find modules and just work with the CMake config files generated by Conan using the CMakeDeps generator.

    I'll update this when I get to try the stable versions of both CMake 3.24 and Conan 2.0.

    How to actually do it (for superprojects using other build systems)

    In order for RmlUi to detect Freetype, the same information from Conan needs to be passed to CMake. Regardless of the integration your build system might have with CMake, your build system needs to run the equivalent to these CLI commands:

    # Compile/download libraries from Conan using the specified profile
    conan install <location_of_conanfile_txt> --build=missing -pr:b=<conan_profile>
    # Go to RmlUi source directory
    cd rmlui
    # Generate project (adjust flags to also specify compiler, build type...)
    cmake -S . -B build \
    -DCMAKE_MODULE_PATH=<location_where_conan_generated_package_files_for_cmake> \
    # Build RmlUi
    cmake --build build --config <build_type>

    Keep in mind the changes in Conan profiles after the release of Conan 2.0 to adapt your commands to the new CLI specification.

  • [Request] <select> list box