JSF2 add custom font to css stylesheet
My stylesheet.css located in META-INF/resources/css/stylesheet.css file
META-INF? So this is bundled in a JAR file which is in turn dropped in webapp's /WEB-INF/lib
?
Regardless, you need to use the #{resource}
resolver instead to resolve classpath resources to proper /javax.faces.resource
URLs .
src: url("#{resource['css:websymbols-regular-webfont.eot']}");
src: url("#{resource['css:websymbols-regular-webfont.eot']}?#iefix") format('embedded-opentype'),
url("#{resource['css:websymbols-regular-webfont.woff']}") format('woff'),
url("#{resource['css:websymbols-regular-webfont.ttf']}") format('truetype'),
url("#{resource['css:websymbols-regular-webfont.svg']}#WebSymbolsRegular") format('svg');
Further, I recommend to put one additional path in /resources
folder which can then represent the real library name. The library="css"
is namely the wrong usage of the resource library. It should not represent specific resource types (CSS/JS/images) at all, but a real common library name. For example, /common
. You can then reference the stylesheet and the resources as follows:
<h:outputStylesheet library="common" name="css/stylesheet.css" />
and
src: url("#{resource['common:css/websymbols-regular-webfont.eot']}");
src: url("#{resource['common:css/websymbols-regular-webfont.eot']}?#iefix") format('embedded-opentype'),
url("#{resource['common:css/websymbols-regular-webfont.woff']}") format('woff'),
url("#{resource['common:css/websymbols-regular-webfont.ttf']}") format('truetype'),
url("#{resource['common:css/websymbols-regular-webfont.svg']}#WebSymbolsRegular") format('svg');
See also:
- What is the JSF resource library for and how should it be used?
- How to reference CSS / JS / image resource in Facelets template?
JSF Custom font with CSS
The final solution: apparently my browser (Chrome) was loading old cached CSS, so I wasn't being able to see the updates I was developing on my styles. Just cleaned Chrome's cache and everything was working perfectly. I just need to figure how to change that behavior on the browser, since I don't want to clean it for every change on my CSS.
Biggest facepalm ever.
EDIT:
Found the solution by opening Devtools -> Settings -> Checked Disable cache (while DevTool is open)
Now I can edit my CSS and refresh the page to normally see the results. Thanks.
Import custom fonts to JSF
Did this using OmniFaces:
Added the dependency (
pom.xml
):<dependency>
<groupId>org.omnifaces</groupId>
<artifactId>omnifaces</artifactId>
<version>1.8.1</version>
</dependency>Added OmniFaces' resource handler to
faces-config.xml
:<application>
<resource-handler>
org.omnifaces.resourcehandler.UnmappedResourceHandler
</resource-handler>
</application>Mapped
/javax.faces.resource/*
toFacesServlet
as follows (web.xml
):<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/javax.faces.resource/*</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>Used
#{resource["<path>"]}
in CSS, like so:@font-face {
font-family: "Gotham Pro Bold";
src: url('#{resource["fonts/GothaProBol.otf"]}');
}
Including Css in jsf
Regarding your XML namespaces
declaration, you are using JSF 2.2.
Since JSF 2.0, you can place CSS, JavaScript files and images(and other files) into a resources directory in the root of your web application.
Then, you can include your CSS using the h:outputStylesheet
:
<h:outputStylesheet library="css" name="styles.css"/>
Reffering to a css stylesheet from an unknown, higher directory
The css file is downloaded and included on the client side, as opposed to the php include
statement which includes the file on the server side.
The path for the css should therefor "make sense" from the clients perspective and probably be specified relative to the public_html
directory. That is, if it resides directly in the public_html
directory the line should read
<link href="/Stylesheet.css" rel="stylesheet" type="text/css" />
Can I make the h:outputStylesheet to load css file that is being retrieved from servlet? (not resources folder)
No, you can't. Even when it has worked, it's the servlet who's responsible for EL resolving, not the <h:outputStylesheet>
component.
You need to solve the problem differently. I'd start by just putting all CSS dependencies, such as CSS images, in the very same folder as the CSS file itself and then reference them relatively. This way you don't need to fiddle with the context path.
By the way, the #{request.contextPath}
is shorter.
JSF 2.0 Javascript and CSS table
If you don't care about IE6 users, just use :hover
pseudoselector. Add the following to your CSS.
table.hovertable tbody tr:hover {
background: #ffff66;
}
If you do care about them for some unobvious reasons, use JavaScript.
var trs = document.getElementById('dataTable').getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++) {
trs[i].onmouseover = new Function("this.bgColor = '#ffff66'");
trs[i].onmouseout = new Function("this.bgColor = '#d4e3e5'");
}
Call it during onload of the window or at end of the body. Note that the element ID dataTable
in the Javascript has to be exactly the same as the generated HTML <table>
ID of the <h:dataTable>
.
<h:dataTable id="dataTable">
This is fancier possible with jQuery.hover()
function, for the case you use jQuery.
$('.hovertable tbody tr').hover(
function() { this.bgColor = '#ffff66'; },
function() { this.bgColor = '#d4e3e5'; }
);
How do I override default PrimeFaces CSS with custom styles?
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:
- How to reference CSS / JS / image resource in Facelets template?
- Mozilla Developer Network > CSS > Specificity (great article, a must read!)
- Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade
Absolute path name in my template to get resources
The template
path in <ui:composition>
is relative to the webapp's own folder structure, not to the domain root (because it does not represent an URL!). So if you start it with /
, it's just resolved relative to the context root.
<ui:composition template="/WEB-INF/inc/template.xhtml">
(putting in /WEB-INF
has the advantage that the enduser cannot open it directly by guessing the URL)
The name
path of <h:outputStylesheet>
, <h:outputScript>
and <h:graphicImage>
is always relative to /resources
root folder, regardless of if you start it with /
or not.
<h:outputStylesheet name="css/default.css" />
<h:outputScript name="js/default.js" />
<h:graphicImage name="img/logo.png" />
If you want to use plain HTML instead of JSF components to include CSS/JS/images for some reason, then best is to prepend the path with #{request.contextPath}
yourself, so that you can make it a domain-relative URL, so that you don't need to fiddle with context-relative URLs. See also: How get the base URL?
Related Topics
CSS Transition Not Working for Percentage Height
Display Footer in Primefaces Template, When Fullpage of P:Layout Is Set to False
Element.Style in Chrome Element Inspector
How to Get Div Height 100% Inside Td of 100%
How to Change Background-Color on Text Links on Hover But Not Image Links
In Less CSS How to Get Less to Watch a Bunch of Files But Compile a Different File When They Change
How to Prevent Child's Content from Stretching Parent's Width
What Happens If Multiple Classes of the Same Element Define a :Before Pseudo-Element
Animate Transform Only One Property (Scale) Override Other (Translate)
Firefox 30.0 - -Moz-Appearance: None Not Working
Ie Background Size Not Working
How to Pass !Important as Parameter/Option for Lesscss Mixins