How do I override default PrimeFaces CSS with custom styles?
Asked Answered
P

5

69

I want to change the size of a PrimeFaces component. For example, a <p:orderList>. It has a class called ui-orderlist-list which is defined in primefaces.css with a fixed 200x200 dimension. No matter what I do in my theme.css, it is overwritten by this attribute and there is no way I can make the content part of a <p:orderList> wider.

For other components I might want to override just one instance of a component, not all.

Can anyone please tell me how can I do all this?

Perot answered 7/1, 2012 at 8:15 Comment(0)
C
139

There are several things you need to take into account of which one or more might be relevant you your specific case

Load your CSS after PrimeFaces one

You need to ensure that your CSS is loaded after the PrimeFaces one. You can achieve this by placing the <h:outputStylesheet> referencing your CSS file inside <h:body> instead of <h:head>:

<h:head>
    ...
</h:head>
<h:body>
    <h:outputStylesheet name="style.css" />
    ...
</h:body>

JSF will automatically relocate the stylesheet to the end of the generated HTML <head> and this will thus ensure that the stylesheet is loaded after the PrimeFaces' default styles. This way the selectors in your CSS file which are exactly the same as in PrimeFaces CSS file will get precedence over the PrimeFaces one.

You'll probably also see suggestions to put it in <f:facet name="last"> of <h:head> which is understood by PrimeFaces-specific HeadRenderer, but this is unnecessarily clumsy and would break when you have your own HeadRenderer.

Understand CSS specificity

You also need to ensure that your CSS selector is at least as specific as the PrimeFaces' default CSS selector on the particular element. You need to understand CSS Specificity and Cascading and Inheritance rules. For example, if PrimeFaces declares a style by default as follows

.ui-foo .ui-bar {
    color: pink;
}

and you declare it as

.ui-bar {
    color: purple;
}

and the particular element with class="ui-bar" happen to have a parent element with class="ui-foo", then the PrimeFaces' one will still get precedence because that's the most specific match!

You can use the webbrowser developer tools to find the exact CSS selector. Rightclick the element in question in the webbrowser (IE9/Chrome/Firefox+Firebug) and choose Inspect Element to see it.

Partial overriding

If you need to override a style for only a specific instance of the component and not all instances of the same component, then add a custom styleClass and hook on that instead. It is another case where specificity is used/applied. For example:

<p:dataTable styleClass="borderless">
.ui-datatable.borderless tbody,
.ui-datatable.borderless th
.ui-datatable.borderless td {
    border-style: none;
}

If a component does not support a styleClass and you are on jsf 2.2 or up, you can also use passtrough attributes and add a pt:class and have it end-up on the output.

<p:clock pt:class="borderless" />

Never use !important

In case you fail to properly load the CSS file in order or to figure the right CSS selector, you'll probably grab the !important workaround. This is Plain Wrong. It's an ugly workaround and not a real solution. It only confuses your style rules and yourself more in long term. The !important should only be used in order to override the values hardcoded in HTML element's style attribute from a CSS stylesheet file on (which is in turn also a bad practice, but in some rare cases unfortunately unavoidable).

See also:

Cardiff answered 8/1, 2012 at 2:45 Comment(4)
A nice trick is to prefix the PrimeFaces selectors with html in order to make them more specific.Brewton
How can I modify CSS based on an element ID like p:dialog id="myDialog"? I have created my own CSS stylesheet with that and added style aiming that ID but it looks like is not working. Web app using PF v5.3Rectilinear
Using !important to overrides foreign CSS from external libraries, like Primefaces or Bootstrap is not a bad practice. Please read the articles that you refer.Woden
@Luis: perhaps you missed the part "The !important should only be used in order to override the values hardcoded in HTML element's style attribute from a CSS stylesheet file on" in the answer.Cardiff
N
6

you can create a new css file for example cssOverrides.css

and place all the overrides you want inside it, that way upgrading the primefaces version wont affect you ,

and in your h:head add something like that

<link href="../../css/cssOverrides.css" rel="stylesheet" type="text/css" />

if it wont work try adding it to the h:body

in order to check if its working try this simple example inside the css file

.ui-widget {
   font-size: 90% !important;
}

this will reduce the size of all primefaces components /text

Noontide answered 7/1, 2012 at 15:36 Comment(0)
C
4

I'm using PrimeFaces 6.0. Here's some information I would have liked to have regarding this:

If you use <h:outputStylesheet/>, it will work, but your CSS will not be loaded last even if it's last in the <h:head></h:head> tags (other CSS files will be included afterwards). A trick you can do which I learned from here is to place it inside <f:facet name="last"></f:facet>, which must go inside the body, like so:

<h:body>
  <f:facet name="last">
    <h:outputStylesheet name="css/MyCSS.css" />
  </f:facet>
...

Then your CSS will be the last loaded. Note: you will still have to adhere to the specificity rules as BalusC outlined.

I placed "MyCSS.css" in WebContent/resources/css/.

More information on the resource loading order: http://www.mkyong.com/jsf2/primefaces/resource-ordering-in-primefaces

Crowded answered 26/1, 2017 at 14:4 Comment(0)
B
4

Load your CSS after PrimeFaces?

Although loading your CSS after the PrimeFaces CSS will override existing rules, I don't thinks it's a good idea. It's better to create more specific rules. More specific rules will always "win", no matter what the order is. If you for example would be using a combined resources handler in combination with PrimeFaces Extension LightSwitch, the switched PrimeFaces theme will be loaded last, making it "win" with equal rules!

How to create more specific rules

The style rules used by PrimeFaces can be quite complex. An element can receive its styling from multiple CSS rules. It's good to know you can use filtering in the DOM inspector's style tab to search on the property you want to customize:

This screenshot was taken using Chrome, but filtering is also available in Firefox and Safari.

When you have found the rule you want to customize, you can simply create a more specific rule by prefixing it with html. For example, your could override .ui-corner-all like:

html .ui-corner-all {
  border-radius: 10px;
}

Use a different theme

Sometimes it's just easier to switch to a different theme and start from there. Have a look at the themes in the showcase.

You might also consider buying a premium theme (disclaimer: I'm not employed by PrimeTek). You can find an overview of templates in the showcase as well.

Using the style attribute

PrimeFaces components can render quite complex HTML. Normally, the style attribute is only applied to the most outer HTML node that the component renders. Also, style is not reusable, so it is better to set a styleClass and create CSS rule(s) based on the class you've set. This also allows you to style inner HTML nodes rendered by the component.

Using the styleClass attribute

PrimeFaces comes with themes (and templates) which have many built in classes. You might find that an existing class will already do the customization you has in mind. For example to remove borders from a p:panelGrid one can simply apply the class ui-noborder. Or the classes that we recently added to PrimeFaces 10 to style buttons, like ui-button-warning.

If you are using PrimeFlex, you can use its classes on components to apply certain styles.

See:

Override a single instance of a component

If you want to override the style of a single instance, use the styleClass attribute to add a CSS class to that instance. You can now use the CSS class you've added in your CSS selectors to create styles.

Replace theme values using a ResourceHandler

I usually just want to replace some color with another value. As colors can be used in many different rules it can be useful to create a ResourceHandler.

In the handler check for the PrimeFaces theme:

@Override
public Resource createResource(String resourceName,
                               String libraryName) {
  if (isPrimeFacesTheme(resourceName, libraryName)) {
    return new MyResource(super.createResource(resourceName, libraryName), this);
  }
  else {
    return getWrapped().createResource(resourceName, libraryName);
  }
}

protected boolean isPrimeFacesTheme(final String resourceName,
                                    final String libraryName) {
  return libraryName != null
                 && libraryName.startsWith("primefaces-")
                 && "theme.css".equals(resourceName);
}

In the resource, replace the color:

private static String cache;

public MyResource(Resource wrapped, ResourceHandler handler) {
  this.wrapped = wrapped;
  this.handler = handler;
  this.charset = Charset.forName(FacesContext.getCurrentInstance().getExternalContext().getRequestCharacterEncoding());
}

@Override
public InputStream getInputStream() throws IOException {
  if (cache == null) {
    cache = readInputStream(getWrapped().getInputStream());
    // Replace values
    cache = cache.replace("#007ad9", "#11dd99");
  }
  return new ByteArrayInputStream(cache.getBytes(charset));
}

And register it as follows in the faces-config.xml:

<application>
  <resource-handler>com.example.MyResourceHandler</resource-handler>
</application>

A resource handler which replaces the accent colors of the Arya, Saga and Vela themes with CSS variables is available in PrimeFaces Extension 10.0.1, see https://www.primefaces.org/showcase-ext/sections/utils/themeAccentColorResourceHandler.jsf.

For more information on resource handlers see:

Brewton answered 5/3, 2018 at 19:43 Comment(0)
D
0

Following the same idea of the accepted answer but without using

<h:outputStylesheet>

and using templates and I must to achieve the goal of load the .css files after the own of Primefaces but at the header block of the page.

enter image description here

template.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    <h:head>
        <title><ui:insert name="title">TEST</ui:insert></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <ui:insert name="headcontent"></ui:insert>
    </h:head>
    <h:body>
        <div id="content">
            <ui:insert name="content"></ui:insert>
        </div>
        <div id="bottom">
            <ui:insert name="bottom"></ui:insert>
        </div>
    </h:body>
</html>

main.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="template.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:f="http://xmlns.jcp.org/jsf/core"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:p="http://primefaces.org/ui"
                xmlns:fn="http://xmlns.jcp.org/jsf/jstl/functions">

    <ui:define name="title">TEST</ui:define>
    <ui:define name="headcontent">
        <link type="text/css" rel="stylesheet" href="../resources/css/index.css"/>
    </ui:define>

    <ui:define name="content">
        ...
    </ui:define>
    
    <ui:define name="bottom">
        ...
    </ui:define>
</ui:composition>

These is an example of how to insert source .css or .scripts files using

<ui:insert>

and

<ui:define>

and as a result the custom .css or .js files are loaded after Primefaces ones and if you look the page info at the browser you can see that these lines are inserted at the end of the header block of the page.

Dictatorship answered 2/8, 2021 at 15:10 Comment(2)
That boils down to https://mcmap.net/q/18097/-how-do-i-override-default-primefaces-css-with-custom-stylesBrewton
Imagine have a big custom .css file. May be is a little tedious having !important; after every line. Nevertheless is not a bad example, it could be useful.Dictatorship

© 2022 - 2024 — McMap. All rights reserved.