Problem
I have a CSS file with some paths in it (for images, fonts, etc.. url(..)).
My path structure is like this:
...
+-src/
| +-MyCompany/
| +-MyBundle/
| +-Resources/
| +-assets/
| +-css/
| +-stylesheets...
+-web/
| +-images/
| +-images...
...
I want to reference my images in the stylesheet.
First Solution
I changed all paths in the CSS file to absolute paths. This is no solution, as the application should (and has to!) be working in a subdirectory, too.
Second Solution
Use Assetic with filter="cssrewrite".
So I changed all my paths in my CSS file to
url("../../../../../../web/images/myimage.png")
to represent the actual path from my resources directory to the /web/images directory. This does not work, since cssrewrite produces the following code:
url("../../Resources/assets/")
which is obviously the wrong path.
After assetic:dump this path is created, which is still wrong:
url("../../../web/images/myimage.png")
The twig code of Assetic:
{% stylesheets
'#MyCompanyMyBundle/Resources/assets/css/*.css'
filter="cssrewrite"
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Current (Third) Solution
Since all CSS files end up in /web/css/stylexyz.css, I changed all paths in the CSS file to be relative:
url("../images/myimage.png")
This (bad) solution works, except in the dev environment:
The CSS path is /app_dev.php/css/stylexyz.css and therefore the image path resulting from this is /app_dev.php/images/myimage.png, which results in a NotFoundHttpException.
Is there a better and working solution?
I have came across the very-very-same problem.
In short:
Willing to have original CSS in an "internal" dir (Resources/assets/css/a.css)
Willing to have the images in the "public" dir (Resources/public/images/devil.png)
Willing that twig takes that CSS, recompiles it into web/css/a.css and make it point the image in /web/bundles/mynicebundle/images/devil.png
I have made a test with ALL possible (sane) combinations of the following:
#notation, relative notation
Parse with cssrewrite, without it
CSS image background vs direct <img> tag src= to the very same image than CSS
CSS parsed with assetic and also without parsing with assetic direct output
And all this multiplied by trying a "public dir" (as Resources/public/css) with the CSS and a "private" directory (as Resources/assets/css).
This gave me a total of 14 combinations on the same twig, and this route was launched from
"/app_dev.php/"
"/app.php/"
and "/"
thus giving 14 x 3 = 42 tests.
Additionally, all this has been tested working in a subdirectory, so there is no way to fool by giving absolute URLs because they would simply not work.
The tests were two unnamed images and then divs named from 'a' to 'f' for the CSS built FROM the public folder and named 'g to 'l' for the ones built from the internal path.
I observed the following:
Only 3 of the 14 tests were shown adequately on the three URLs. And NONE was from the "internal" folder (Resources/assets). It was a pre-requisite to have the spare CSS PUBLIC and then build with assetic FROM there.
These are the results:
Result launched with /app_dev.php/
Result launched with /app.php/
Result launched with /
So... ONLY
- The second image
- Div B
- Div C
are the allowed syntaxes.
Here there is the TWIG code:
<html>
<head>
{% stylesheets 'bundles/commondirty/css_original/container.css' filter="cssrewrite" %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{# First Row: ABCDEF #}
<link href="{{ '../bundles/commondirty/css_original/a.css' }}" rel="stylesheet" type="text/css" />
<link href="{{ asset( 'bundles/commondirty/css_original/b.css' ) }}" rel="stylesheet" type="text/css" />
{% stylesheets 'bundles/commondirty/css_original/c.css' filter="cssrewrite" %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets 'bundles/commondirty/css_original/d.css' %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets '#CommonDirtyBundle/Resources/public/css_original/e.css' filter="cssrewrite" %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets '#CommonDirtyBundle/Resources/public/css_original/f.css' %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{# First Row: GHIJKL #}
<link href="{{ '../../src/Common/DirtyBundle/Resources/assets/css/g.css' }}" rel="stylesheet" type="text/css" />
<link href="{{ asset( '../src/Common/DirtyBundle/Resources/assets/css/h.css' ) }}" rel="stylesheet" type="text/css" />
{% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/i.css' filter="cssrewrite" %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/j.css' %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets '#CommonDirtyBundle/Resources/assets/css/k.css' filter="cssrewrite" %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
{% stylesheets '#CommonDirtyBundle/Resources/assets/css/l.css' %}
<link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}
</head>
<body>
<div class="container">
<p>
<img alt="Devil" src="../bundles/commondirty/images/devil.png">
<img alt="Devil" src="{{ asset('bundles/commondirty/images/devil.png') }}">
</p>
<p>
<div class="a">
A
</div>
<div class="b">
B
</div>
<div class="c">
C
</div>
<div class="d">
D
</div>
<div class="e">
E
</div>
<div class="f">
F
</div>
</p>
<p>
<div class="g">
G
</div>
<div class="h">
H
</div>
<div class="i">
I
</div>
<div class="j">
J
</div>
<div class="k">
K
</div>
<div class="l">
L
</div>
</p>
</div>
</body>
</html>
The container.css:
div.container
{
border: 1px solid red;
padding: 0px;
}
div.container img, div.container div
{
border: 1px solid green;
padding: 5px;
margin: 5px;
width: 64px;
height: 64px;
display: inline-block;
vertical-align: top;
}
And a.css, b.css, c.css, etc: all identical, just changing the color and the CSS selector.
.a
{
background: red url('../images/devil.png');
}
The "directories" structure is:
Directories
All this came, because I did not want the individual original files exposed to the public, specially if I wanted to play with "less" filter or "sass" or similar... I did not want my "originals" published, only the compiled one.
But there are good news. If you don't want to have the "spare CSS" in the public directories... install them not with --symlink, but really making a copy. Once "assetic" has built the compound CSS, and you can DELETE the original CSS from the filesystem, and leave the images:
Compilation process
Note I do this for the --env=prod environment.
Just a few final thoughts:
This desired behaviour can be achieved by having the images in "public" directory in Git or Mercurial and the "css" in the "assets" directory. That is, instead of having them in "public" as shown in the directories, imagine a, b, c... residing in the "assets" instead of "public", than have your installer/deployer (probably a Bash script) to put the CSS temporarily inside the "public" dir before assets:install is executed, then assets:install, then assetic:dump, and then automating the removal of CSS from the public directory after assetic:dump has been executed. This would achive EXACTLY the behaviour desired in the question.
Another (unknown if possible) solution would be to explore if "assets:install" can only take "public" as the source or could also take "assets" as a source to publish. That would help when installed with the --symlink option when developing.
Additionally, if we are going to script the removal from the "public" dir, then, the need of storing them in a separate directory ("assets") disappears. They can live inside "public" in our version-control system as there will be dropped upon deploy to the public. This allows also for the --symlink usage.
BUT ANYWAY, CAUTION NOW: As now the originals are not there anymore (rm -Rf), there are only two solutions, not three. The working div "B" does not work anymore as it was an asset() call assuming there was the original asset. Only "C" (the compiled one) will work.
So... there is ONLY a FINAL WINNER: Div "C" allows EXACTLY what it was asked in the topic: To be compiled, respect the path to the images and do not expose the original source to the public.
The winner is C
The cssrewrite filter is not compatible with the #bundle notation for now. So you have two choices:
Reference the CSS files in the web folder (after: console assets:install --symlink web)
{% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
Use the cssembed filter to embed images in the CSS like this.
{% stylesheets '#MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}
I'll post what worked for me, thanks to #xavi-montero.
Put your CSS in your bundle's Resource/public/css directory, and your images in say Resource/public/img.
Change assetic paths to the form 'bundles/mybundle/css/*.css', in your layout.
In config.yml, add rule css_rewrite to assetic:
assetic:
filters:
cssrewrite:
apply_to: "\.css$"
Now install assets and compile with assetic:
$ rm -r app/cache/* # just in case
$ php app/console assets:install --symlink
$ php app/console assetic:dump --env=prod
This is good enough for the development box, and --symlink is useful, so you don't have to reinstall your assets (for example, you add a new image) when you enter through app_dev.php.
For the production server, I just removed the '--symlink' option (in my deployment script), and added this command at the end:
$ rm -r web/bundles/*/css web/bundles/*/js # all this is already compiled, we don't need the originals
All is done. With this, you can use paths like this in your .css files: ../img/picture.jpeg
I had the same problem and I just tried using the following as a workaround. Seems to work so far. You can even create a dummy template that just contains references to all those static assets.
{% stylesheets
output='assets/fonts/glyphicons-halflings-regular.ttf'
'bundles/bootstrap/fonts/glyphicons-halflings-regular.ttf'
%}{% endstylesheets %}
Notice the omission of any output which means nothing shows up on the template. When I run assetic:dump the files are copied over to the desired location and the css includes work as expected.
If it can help someone, we have struggled a lot with Assetic, and we are now doing the following in development mode:
Set up like in Dumping Asset Files in the dev Environmen so in config_dev.yml, we have commented:
#assetic:
# use_controller: true
And in routing_dev.yml
#_assetic:
# resource: .
# type: assetic
Specify the URL as absolute from the web root. For example, background-image: url("/bundles/core/dynatree/skins/skin/vline.gif"); Note: our vhost web root is pointing on web/.
No usage of cssrewrite filter
I offen manage css/js plugin with composer which install it under vendor.
I symlink those to the web/bundles directory, that's let composer update bundles as needed.
exemple:
1 - symlink once at all (use command fromweb/bundles/
ln -sf vendor/select2/select2/dist/ select2
2 - use asset where needed, in twig template :
{{ asset('bundles/select2/css/fileinput.css) }}
Regards.
Related
I just started to use symfony to make a website. I'm really new to this but still with internet and all the documentation i manage to understand how it basically work and i figured out how to use the assets for my css code on symfony. I've got my asset configured with the entry and everything else seems to work. Even my public dir seems to be ok. Now when i tried to write some css it doesn't seems to load on my home page :/. Can someone help me with this ? Thanks for your help ! :)
HERE'S MY WEBPACK.CONFIG.JS
// directory where compiled assets will be stored
.setOutputPath('public/build')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
//.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
.addEntry('style', './assets/css/app.css')
HERE'S MY BASE.TWIG.HTML FILE
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
{% block stylesheets %}<link rel="stylesheet" href="{{ asset('/build/css/style.css') }}">{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
HERE'S THE HEAD OF THE PAGE WHERE I WANT TO APPLY THE CSS ON
{% extends 'base.html.twig' %}
{% block body%}
<h1>welcome</h1>
<img src="" alt="Home pic" class="bckPic">
<!-- About -->
<h2 class="headTitle">About</h2>
<div class="row">
<p class="col">blablablablablabla</p>
<img class="col" src="" alt="logo">
</div>
Your code seem to be correct.
Try to change
`<link rel="stylesheet" href="{{ asset('/build/css/style.css') }}">`
with
{{ encore_entry_link_tags('style') }}
"style" is entry name in your webpack.config.js -> .addEntry('style', './assets/css/app.css')
Then in command line go to source root folder and run:
yarn install
#for develop env
yarn encore dev
#for prod env
#yarn encore prod
and refresh page
See: https://symfony.com/doc/current/frontend/encore/installation.html
I use asseticBundle for my files but when I use php app/console assets:install and php app/console assetic:dump, all my files are transfered except images.
{% block stylesheets %}
{% stylesheets filter='cssrewrite'
'#BattutaBackBundle/Resources/public/libs/bootstrap/css/bootstrap.min.css'
'#BattutaBackBundle/Resources/public/libs/font-awesome/css/font-awesome.min.css'
'#BattutaBackBundle/Resources/public/libs/iCheck/skins/flat/green.css'
'#BattutaBackBundle/Resources/public/libs/animate/css/animate.css'
'#BattutaBackBundle/Resources/public/libs/custom.css'
%}
<link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}
{% endblock %}
I have images like green.png but they not transfered. that image file is important because I use it for checkbox background. How can I do ?
If you are talking about resources referenced inside css files:
Symfony2 - Assetic - load images in CSS
You need to use css filters which will process the css and get images required and dump them appropriately.
And you cant use #Bundle syntax for this feature.
I have trouble referencing images from my .css file in a symfony2 project. I have a main.css in app/Resources/public/css and my image directory is app/Resources/public/images.
I include the css sheet like so:
{% stylesheets '../app/Resources/public/css/*' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
How would I go about referencing images in my css file?
Use ../ to go to the previous directory (app/Respirces/public/), then proceed with the rest of the URL.
selector {
background-image: url(../images/image.png);
}
Inori's answer helped me with this issue:
Symfony2 - Assetic - load images in CSS
In the end I had to run assetic:dump and then referenced images like this:
background-image: url('/images/background.jpg');
I'm currently developing a web application using Symfony 2.1.0.
I've read through the Templating chapter of the book and I'm trying to include assets (right now, it's just a single stylesheet) in my web pages.
I'm using the Three-level inheritance system that is mentioned in the book, and my application structure currently looks like this:
app/Resources/views/
base.html.twig: base template, containing title, stylesheets and body blocks.
src/My/PageBundle/Resources/views
layout.html.twig: layout template (extending the base template), appending the main stylesheet to the stylesheet block, and overwriting the body block, including navigation.html.twig and defining a content block
layout-admin.html.twig: same thing as above, but including navigation-admin.html.twig
src/My/PageBundle/Resources/views/Main
standard templates, extending the layout template and overwriting its content block
src/My/PageBundle/Resources/views/Administration
administration templates. Same thing as above, but extending the administration layout template.
src/My/PageBundle/Resources/public/css
main.css: main stylesheet
As you can see, I have put the stylesheet in my bundle. I don't know whether this is good practice or not.
Now, the thing is, in layout.html I added this:
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" type="text/css" href="{{ asset('css/main.css)' }}" />
{% endblock %}
But asset('css/main.css') is just linking to /css/main.css, whereas ./app/console assets:install installs the assets in web/bundles/mypagebundle/. I don't like the fact that this way, my bundle name would be publicly visible (which could make users suspect I'm using Symfony, and I like keeping the internals of my webpage, well, internal). Is it possible to change the directory where assets:install would install the assets? It seems tedious to me to manually install the assets in web/.
I'm also thinking about using Assetic for asset management, as I personally like the possibility to automatically minify my scripts/stylesheets and store them all together in one file. However, I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system. Is it possible to work around that? Also, would using Assetic enable me to hide my bundle name from the public?
Using assetic would address all your issues.
I hear that this is not possible if you include stylesheets at different levels, i.e. it wouldn't work with the three-level inheritance system
You can, but it will generate a css file for each level (just like with asset(), actually).
Example:
layout:
{% block stylesheets %}
{{ parent() }}
{% stylesheets 'main.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
sub-template:
{% block stylesheets %}
{{ parent() }}
{% stylesheets 'sub.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
result:
<link rel="stylesheet" type="text/css" href="..." />
<link rel="stylesheet" type="text/css" href="..." />
Alternatively sub-template can completly override the stylesheets block, so that only one stylesheet is generated (but it's less dry):
{% block stylesheets %}
{% stylesheets 'main.css' 'sub.css' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
result (in production / non debug):
<link rel="stylesheet" type="text/css" href="..." />
In the html file i can access the images folder using asset function but in my css i am not able to us e images
background-image:url(../images/back.png)
{% stylesheets 'css/*' %}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
How to fix that
I use this:
background-image: url(/bundles/yourbundle/images/pic.png)
Works without cssrewrite filter.
This is something that always puzzles me as well! Anyway there is a cssrewrite assetic filter that should help you to solve this problem detecting and rewriting urls in css scripts (anyway, even using this, you may need to change urls in your css).