41

I often, change the images of my buttons using the image attribute, but someone told me that it is a good practice to do it using .css I tried but i cant, what i am doing wrong? This is what i did:

1-The resources of my project are stored like this:

enter image description here

2-This is how i created the style.css for accessing the image

.c2 {
    background: url(/resources/images/smiley.jpg);  
}

3-This is how i access the css from the body of my page(Im sure this is correct because other classes in the same document works in other tags in this page)

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

4-This is how create a sample commandButton that uses the appropiated css class

<h:commandButton styleClass="c2"/>

I think the problem is in the .css, i tried a few combinations but none worked:

background-image: url(/resources/images/smiley.jpg);    
background: url(resources/images/smiley.jpg);   
background: url(smiley.jpg);    
background: url(../smiley.jpg); 

Where is the mistake?

update I managed to make it work by the following code:

.c2 {   
     background: url("#{resource['images:smiley.jpg']}");               
    }

Notice the difference when i use css(right) and when i use image attribute(left)

enter image description here

How could i solve this so the hold image is shown?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
javing
  • 12,307
  • 35
  • 138
  • 211

2 Answers2

78

When importing CSS stylesheets by <h:outputStylesheet>, the stylesheet is imported and processed by the FacesServlet through /javax.faces.resource/*. Look at the generated <link> element pointing to the stylesheet in question and you'll understand.

You have to change all url() dependencies to use #{resource['library:location']} instead. JSF will then auto-substitute it with the right path. Given your folder structure, you need to replace

.c2 {
    background: url("/resources/images/smiley.jpg");  
}

by

.c2 {
    background: url("#{resource['images/smiley.jpg']}");  
}

Assuming that your webapp context name is playground and that your FacesServlet is mapped on *.xhtml, then the above should end up in the returned CSS file as follows

.c2 {
    background: url("/playground/javax.faces.resource/images/smiley.jpg.xhtml");
}

Noted should be that the JSF implementation will for determine only during the first request on the CSS file if it contains EL expressions. If it doesn't then it will for efficiency not anymore attempt to EL-evaluate the CSS file content. So if you add an EL expression to a CSS file for the first time, then you'd need to restart the whole application in order to get JSF to re-check the CSS file.

In case you wanted to reference a resource from a component library such as PrimeFaces, then prefix the library name, separated with :. E.g. when you're using PrimeFaces "Start" theme which is identified by primefaces-start

.c2 {
    background: url("#{resource['primefaces-start:images/ui-bg_gloss-wave_50_6eac2c_500x100.png']}");  
}

This will be generated as

.c2 {
    background: url("/playground/javax.faces.resource/images/ui-bg_gloss-wave_50_6eac2c_500x100.png.xhtml?ln=primefaces-start");
}

See also:


Unrelated to the concrete problem, the way how you use the library is not entirely right. It's meant to be the common identifier/subfolder of all related CSS/JS/image resources. The key idea is to be able to change the entire look'n'feel by just changing the library (which can be done by EL). You seem however to be relying on the default library. In that case, you could just omit the library from your <h:outputStylesheet> and #{resource}.

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

See also:

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I saw the generated code in the page:`` I notice than before when i used the image attribute instead of css, i saw this: `` The code you gave for class .c2 didn't work but at the link you pasted at the end there is an example that works for me in a similar way, but only if i change the background of the page, does not work for .css class – javing Aug 03 '11 at 12:29
  • 1
    Are you using PrimeFaces or some other rich UI component library? It ships with default backgrounds bundled. You'd like to override it. You can do it by adding `!important` to the end of the CSS property like as `background: url(#{resource['images:smiley.jpg']}) !important;`. – BalusC Aug 03 '11 at 12:32
  • No currently in this project there is no Primefaces or similar, just JSF 2.0. I noticed your codes do not include quotes `""`, i also tried like this `background: url("#{resource['images:smiley.jpg']}")` but only doesnt work for the css classes – javing Aug 03 '11 at 12:40
  • Open the webpage in Firefox. Rightclick, *View Source*. Locate the `` pointing to the CSS file in question. Click its `href`. You'll see the generated CSS source. Is the `#{resource}` properly been resolved? It should look something like `/contextname/javax.faces.resource/smiley.jpg.xhtml?ln=images` (the `.xhtml` prefix/suffix depends on `FacesServlet`'s own URL pattern). And, in Firebug open the *Net* panel. Reload the page. Is the `smiley.jpg.xhtml` been loaded successfully (i.e. 2nn or 3nn response)? – BalusC Aug 03 '11 at 12:43
  • 1
    The quotes are only mandatory if the path contains spaces. You are however free to include them. Another debug help: in Firefox with Firebug, rightclick the button element, choose *Inspect Element*. Verify the *Style* panel on the right hand side of Firebug. Is all right? – BalusC Aug 03 '11 at 12:50
  • Just did that, and i see it works .I got confused, becouse the background is white.(See my update) – javing Aug 03 '11 at 12:53
  • 2
    Just specify a fixed width and height on `.c2` :) E.g. `width: 75px; height: 75px;`, depending on the image's exact dimensions. You'd probably also like to add a `border: 0;` and play somewhat with margin/padding/overflow (MSIE!). In the future, you should try to be really more clear about "It doesn't work". You saw only a part of the image. The concrete problem of image not being loaded was already solved! – BalusC Aug 03 '11 at 12:54
  • You are right, but i will be more careful next time. Thanks for your help Balus :) – javing Aug 03 '11 at 16:59
  • I tried this, and it does work, the thing is that ever since I did this, loading the pages takes a whole bunch of time. I have hundreds of images in my css, used as backgrounds, icons, sprites, etc. Could it be that resolving all the EL expressions is slowing me down here? any way to cache it? – arg20 Feb 20 '12 at 23:38
1

Since I struggled with this a little bit and while BalusC has already answered the question but might be able to comment as to why this is happening. I have 5 EAR projects consisting of a bundled WAR and EJB projects. I then have one standalone WAR project deployed on its own. The following code worked perfect with all the EAR's:

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>Super FIPS Calculator PRO</title>
    <style>              
        .Bimage{background-image:url(#{request.contextPath}/img/phonetoolsBackground.png);}
    </style>
</h:head>
<h:body styleClass="Bimage">
.
.
.

Where the "img" folder was within the WEB-INF folder but for the EAR project, it would not work and it wouldnt even load the picture in the browser by manually typing in the URL. I verified the resulting html was 100% accurate. So all the talk of "resources" got me thinking that maybe it was a ?security? issue of some sort which doesnt seem to make sense between the WAR and EAR deployments so I created a "resources" folderin the root of the web application, e.g. in Eclipse its parent would be WebContent, then added a subfolder to resources called "img", placed my image in there.

The code now looks like this:

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>Super FIPS Calculator PRO</title>
    <style>              
        .Bimage{background-image:url(#{request.contextPath}/resources/img/phonetoolsBackground.png);}
    </style>
</h:head>
<h:body styleClass="Bimage">
.
.
.

And now the image is displayed. Again not trying to hijack balusc's thorough answer, I just wanted to bring it up in case anyone ran into a similar issue. If someone wants me to open a separate Q and A I will!

Ahh yes, this was on JBoss EAP 7, Servlet API 3.1, Facelets 2.2, Rich Faces 4.5.17 Java 1.8.

Edit @Basil-Bourque answer What is WEB-INF used for in a Java EE web application seems fairly relevant

But its still a little confusing in that how can a WAR within an EAR access that location but not a standalone WAR?

JGlass
  • 1,427
  • 2
  • 12
  • 26