HowTo create a custom Redmine theme » History » Version 13
Takashi Kato, 2025-09-28 09:50
| 1 | 1 | Jean-Philippe Lang | h1. HowTo create a custom Redmine theme |
|---|---|---|---|
| 2 | |||
| 3 | 5 | Jean-Philippe Lang | Redmine offers basic support for themes. Themes can override stylesheets (application.css) and add some custom javascript. |
| 4 | 1 | Jean-Philippe Lang | |
| 5 | 13 | Takashi Kato | NOTE: From Redmine 6.0, the location for themes changed from @public/themes@ to @themes@. If you are creating a theme for a version prior to 6.0, please read @themes as @public/themes in the following instructions. |
| 6 | |||
| 7 | 1 | Jean-Philippe Lang | h2. Creating a new theme |
| 8 | |||
| 9 | 13 | Takashi Kato | Create a directory in @/themes@. The directory name will be used as the theme name. |
| 10 | 1 | Jean-Philippe Lang | |
| 11 | Example: |
||
| 12 | |||
| 13 | 13 | Takashi Kato | themes/my_theme |
| 14 | 1 | Jean-Philippe Lang | |
| 15 | 4 | Jean-Philippe Lang | Create your custom @application.css@ and save it in a subdirectory named @stylesheets@: |
| 16 | 1 | Jean-Philippe Lang | |
| 17 | 13 | Takashi Kato | themes/my_theme/stylesheets/application.css |
| 18 | 1 | Jean-Philippe Lang | |
| 19 | 2 | Jean-Philippe Lang | Here is an example of a custom stylesheet that only override a few settings: |
| 20 | 1 | Jean-Philippe Lang | |
| 21 | 11 | Toshi MARUYAMA | <pre><code class="css"> |
| 22 | /* load the default Redmine stylesheet */ |
||
| 23 | 2 | Jean-Philippe Lang | @import url(../../../stylesheets/application.css); |
| 24 | 1 | Jean-Philippe Lang | |
| 25 | 2 | Jean-Philippe Lang | /* add a logo in the header */ |
| 26 | #header { |
||
| 27 | background: #507AAA url(../images/logo.png) no-repeat 2px; |
||
| 28 | padding-left: 86px; |
||
| 29 | } |
||
| 30 | |||
| 31 | 10 | Go MAEDA | |
| 32 | 2 | Jean-Philippe Lang | /* move the project menu to the right */ |
| 33 | #main-menu { |
||
| 34 | left: auto; |
||
| 35 | right: 0px; |
||
| 36 | 1 | Jean-Philippe Lang | } |
| 37 | </code></pre> |
||
| 38 | |||
| 39 | This example assume you have an image located at @my_theme/images/logo.png@. |
||
| 40 | |||
| 41 | 13 | Takashi Kato | You can download this sample theme as a starting point for your own theme. Extract it in the @/themes@ directory. |
| 42 | 1 | Jean-Philippe Lang | |
| 43 | 13 | Takashi Kato | *NOTE*: From Redmine 6.0, The code @@import url(../../../stylesheets/application.css)@ shown in the example above is automatically converted to @@import url(“/assets/application-29b28b2c.css”);@ when Redmine starts. The combination of numbers and letters at the end of the filename is a hash value calculated from the file's contents. Since the filename changes whenever the content is modified, issues like display corruption caused by browsers using outdated cached versions are avoided. |
| 44 | 1 | Jean-Philippe Lang | |
| 45 | 13 | Takashi Kato | h2. Adding custom JavaScript |
| 46 | 1 | Jean-Philippe Lang | |
| 47 | 13 | Takashi Kato | Simply put your JavaScript in @javascripts/theme.js@ and it will automatically be loaded on each page. |
| 48 | 1 | Jean-Philippe Lang | |
| 49 | 13 | Takashi Kato | *NOTE*: From Redmine 6.0, When specifying image paths in JavaScript, use the @RAILS_ASSET_URL@ pseudo-method as shown in the example below. For more detailed conversion specifications, refer to "README of propshaft":https://github.com/rails/propshaft?tab=readme-ov-file#referencing-digested-assets-in-css-and-javascript |
| 50 | |||
| 51 | Source: |
||
| 52 | <pre class="javascript"> |
||
| 53 | export default class extends Controller { |
||
| 54 | init() { |
||
| 55 | this.img = RAILS_ASSET_URL("/icons/trash.svg") |
||
| 56 | } |
||
| 57 | } |
||
| 58 | </pre> |
||
| 59 | |||
| 60 | Transformed: |
||
| 61 | <pre class="javascript"> |
||
| 62 | export default class extends Controller { |
||
| 63 | init() { |
||
| 64 | this.img = "/assets/icons/trash-54g9cbef.svg" |
||
| 65 | } |
||
| 66 | } |
||
| 67 | </pre> |
||
| 68 | |||
| 69 | 1 | Jean-Philippe Lang | h2. Setting a Favicon |
| 70 | |||
| 71 | Put your favicon in @favicon@ directory and it will automatically be loaded instead of default one on each page. The name of the favicon file can be anything. |
||
| 72 | |||
| 73 | h2. Applying the theme |
||
| 74 | |||
| 75 | Go to "Administration -> Settings" and select your newly created theme in the "Theme" drop-down list. Save your settings. |
||
| 76 | Redmine should now be displayed using your custom theme. |
||
| 77 | |||
| 78 | 10 | Go MAEDA | h2. Directory structure of themes |
| 79 | |||
| 80 | A theme consists of the following files: |
||
| 81 | |||
| 82 | * @favicon/<favicon file>@ (optional): favicon for the theme |
||
| 83 | * @javascripts/theme.js@ (optional): custom JavaScript for the theme |
||
| 84 | * @stylesheets/application.css@ (required): CSS for the theme |
||
| 85 | |||
| 86 | |||
| 87 | <pre> |
||
| 88 | 13 | Takashi Kato | themes/ |
| 89 | +- <theme name>/ |
||
| 90 | | |
||
| 91 | +- favicon/ |
||
| 92 | | +- <favicon file> (e.g. favicon.ico, favicon.png) |
||
| 93 | | |
||
| 94 | +- javascripts/ |
||
| 95 | | +- theme.js |
||
| 96 | | |
||
| 97 | +- stylesheets/ |
||
| 98 | +- application.css |
||
| 99 | 10 | Go MAEDA | </pre> |