zulip/docs/subsystems/html-css.md

5.2 KiB

HTML and CSS

Zulip CSS organization

The Zulip application's CSS can be found in the static/styles/ directory. Zulip uses Bootstrap as its main third-party CSS library.

Zulip uses SCSS for its CSS files. There are two high-level sections of CSS: the "portico" (logged-out pages like /help/, /login/, etc.), and the app. The portico CSS lives under the static/styles/portico subdirectory.

Editing Zulip CSS

If you aren't experienced with doing web development and want to make CSS changes, we recommend reading the excellent Chrome web inspector guide on editing HTML/CSS, especially the section on CSS to learn about all the great tools that you can use to modify and test changes to CSS interactively in-browser (without even having the reload the page!).

Zulip's development environment has hot code reloading configured, so changes made in source files will immediately take effect in open browser windows, either by live-updating the CSS or reloading the browser window (following backend changes).

CSS Style guidelines

Avoid duplicated code

Without care, it's easy for a web application to end up with thousands of lines of duplicated CSS code, which can make it very difficult to understand the current styling or modify it. We would very much like to avoid such a fate. So please make an effort to reuse existing styling, clean up now-unused CSS, etc., to keep things maintainable.

Be consistent with existing similar UI

Ideally, do this by reusing existing CSS declarations, so that any improvements we make to the styling can improve all similar UI elements.

Use clear, unique names for classes and object IDs

This makes it much easier to read the code and use git grep to find where a particular class is used.

Validating CSS

When changing any part of the Zulip CSS, it's important to check that the new CSS looks good at a wide range of screen widths, from very wide screen (e.g. 1920px) all the way down to narrow phone screens (e.g. 480px).

For complex changes, it's definitely worth testing in a few different browsers to make sure things look the same.

HTML templates

Behavior

  • Templates are automatically recompiled in development when the file is saved; a refresh of the page should be enough to display the latest version. You might need to do a hard refresh, as some browsers cache webpages.

  • Variables can be used in templates. The variables available to the template are called the context. Passing the context to the HTML template sets the values of those variables to the value they were given in the context. The sections below contain specifics on how the context is defined and where it can be found.

Backend templates

For text generated in the backend, including logged-out ("portico") pages and the webapp's base content, we use the Jinja2 template engine (files in templates/zerver).

The syntax for using conditionals and other common structures can be found here.

The context for Jinja2 templates is assembled from a few places:

  • zulip_default_context in zerver/context_processors.py. This is the default context available to all Jinja2 templates.

  • As an argument in the render call in the relevant function that renders the template. For example, if you want to find the context passed to index.html, you can do:

$ git grep zerver/app/index.html '*.py'
zerver/views/home.py:    response = render(request, 'zerver/app/index.html',

The next line in the code being the context definition.

  • zproject/urls.py for some fairly static pages that are rendered using TemplateView, for example:
url(r'^config-error/google$', TemplateView.as_view(
    template_name='zerver/config_error.html',),
    {'google_error': True},),

Frontend templates

For text generated in the frontend, live-rendering HTML from JavaScript for things like the main message feed, we use the Handlebars template engine (files in static/templates/) and sometimes work directly from JavaScript code (though as a policy matter, we try to avoid generating HTML directly in JavaScript wherever possible).

The syntax for using conditionals and other common structures can be found here.

There's no equivalent of zulip_default_context for the Handlebars templates.

Toolchain

Handlebars is in our package.json and thus ends up in node_modules; We use handlebars-loader to load and compile templates during the webpack bundling stage. In the development environment, webpack will trigger a browser reload whenever a template is changed.

Translation

All user-facing strings (excluding pages only visible to sysadmins or developers) should be tagged for translation.