Loading different css files selectively


#1

hey

say I wanna have 2 css app files, A and B, and I’d like to decide which css to stream down to the client by some data in the initial HTTP request

any thoughts?


#2

I’ve actually hit this issue a lot. The only way I got past it was namespacing my css and using very specific selectors. It may not be the “meteor” way of doing this but I figured since everything gets loaded into the client anyways, you’re not really going to make a difference with performance as far as I understand it so it’s really just a matter of specifying what you want styled and being detailed in your selectors.

Only downside I’ve been able to think of is if you want to override a style, but then again, why not just change the rule in the original CSS? It’s all going to the same place.


#3

there’s a sound reason for what I’m trying to do

I generate an RTL version of the original CSS produced by the Meteor build chain
Now, RTL users wouldn’t need to download the original LTR css file, and vice versa

so the point is to load initially only the needed direction file


#4

Why not put something like:

$('head').append('<link id="currentTheme" rel="stylesheet" href="/bootstrap/css/custom.css" type="text/css" />');

in an if statement in Meteor.startup?


#5

that means the original css file still loads

(that’s my current solution)


#6

Just out of curiosity, what kind of file size are we talking here in regards to the original CSS vs the RTL CSS?


#7

since the RTL conversion is automatic (i.e. copy all styles and invert directional properties), the files are about the same in size

If I do have to settle for sending 2 files to the client, perhaps I would have to generate just the differences


#8

Here a part of my head.html in my client folder:

<link href="/assets/metronic/theme_rtl/assets/global/plugins/bootstrap/css/bootstrap.min.css"
              id="headLinkCss_bootstrap"
              rel="stylesheet"
              type="text/css">
        <link href="/assets/metronic/theme_rtl/assets/global/plugins/bootstrap-switch/css/bootstrap-switch.min.css"
              id="headLinkCss_bootstrap-switch"
              rel="stylesheet"
              type="text/css"/>

Note: each link has a unique “id”. The head.html is loaded by default in meteor and appended after all the other header parts that meteor and the packages generate.

In my client folder I have a coffeescript file with the following:

Meteor.startup ->
# code to run on client at startup
# The following will load the RTL templates based on the value of the orientationLeftToRightIndicator Session variable

  Session.setDefault 'orientationLeftToRightIndicator', 'left'

  cssList =
    [
      {
        id: "headLinkCss_bootstrap"
        css:
          "left": "/assets/metronic/theme_rtl/assets/global/plugins/bootstrap/css/bootstrap.min.css"
          "right": "/assets/metronic/theme_rtl/assets/global/plugins/bootstrap/css/bootstrap-rtl.min.css"
      },
      {
        id: "headLinkCss_bootstrap-switch"
        css:
          left: "/assets/metronic/theme_rtl/assets/global/plugins/bootstrap-switch/css/bootstrap-switch.min.css"
          right: "/assets/metronic/theme_rtl/assets/global/plugins/bootstrap-switch/css/bootstrap-switch.min.css"
      }
    ]

  Deps.autorun ->
    orientation = Session.get('orientationLeftToRightIndicator')
    # orientation = 'right'
    _.each cssList, (elem) ->
      $('link#' + elem.id).attr 'href', elem.css[orientation]
      # $('link#headLinkCss_bootstrap').attr 'href', '/assets/metronic/theme_rtl/assets/global/plugins/bootstrap/css/bootstrap.min.css'

Depending on the value of the session variable “orientationLeftToRightIndicator”, either “left” or “right” I choose which css to load from the array and replace the href attribute value of the appropriate head link. More css require an appending of the new css in the head.html, as well as the appending of the css array to specify which css to load for left orientation and which for the right orientation.

The autorun makes the loading of the css reactive, so changing the value of “orientationLeftToRightIndicator” will dynamically change the orientation on the screen.

There will probably be a much better and less verbose way to do this, but it seems to work.

Regards

Rudolf


#9

Hey Rudolf

thanks for sharing your thoughts and execution

However, the public css approach means that you can’t use the standard ‘less’ package build chain to bundle all of your project’s css in one file

my specific use case is that I need to make sure ALL styles are RTL-friendly (not just a library, e.g. bootstrap), which is best done if you use the project’s bundled css, as it contains all styles in the project and included packages


#10

Hi @chenroth,

Yes, the “solution” does prevent one from using the less package workflow.

My starting point is probably many, many steps behind yours. In order to not have to bother with styling, but still get a decent looking app, I decided to buy a standard theme for 27USD which had RTL support and implement that theme, up until I get to the point where I actually understand what I am doing and have the skill set to do this stuff myself. Comparing the RTL and LTR css files showed hundreds and hundreds of differences. It was just too many to implement some form of dynamic switching of the themes within the templates based on the current meteor workflow of combining CSS files. An option might have been to extract the differences, and then write the differences as part of the HTML of the web page itself (embedded style in the head), which would override the styles in the CSS. That would have made the changes reactive, allowed me to use the standard workflow for merging the CSS into one file, but it just did not seem to be worth the effort at the time. The next time they update the stylesheets I would have to filter through all the stylesheets finding and implementing the changes in my code. And many of the differences are by omission, where a property is not set in one of the CSS files. My “solution” is just a path of least resistance.

If you do find a workable solution I for one would be very grateful if you could post your solution workflow.

Regards

Rudolf


#11

I know the issue quite well, too.
For me it was about serving a dedicate mobile.css vs desktop.css - and yes, I’m also using the Less compiler. The only usable solution to keep the workflow of Meteor was to namespace the style, i.e. send both mobile and desktop down the wire and let CSS take care of the rest.
With some serious, responsive design, the file is big! 200k+ and that’s a pain for mobile to be loaded fully before the app shows correctly - plus, I also believe that it will use more computational power on the mobile to handle this huge CSS file.

I’d love to see a configuration/switch in Meteor allowing me to override the default “include all CSS” to “manual”, e.g. defining folders and each folder will procude one compiled and minified file (or point to particular Less files and they will defined their imports manually), and ideally define one “common CSS” that will be included for sure - e.g. a reset.css.


#12

Hi chen have you manged to solve this issue


#13

In a way, yes. It’s been a while now and I’ve since moved on from that
product, but i recall using 2 css files which i swap live on the client
browser when demanded. I use visuals to hide the brief transition between
the styles (i.e. a white loading screen). The alternative css (RTL for
hebrew ui) is auto generated as described in a previous post by a node
script i wrote, which watches for change in the build css


#14

Thank you for the quick replay chen may i just ask how would you make that tarnsition ?
Because im using this the packge “alonw:bootstrap-rtl” and as soon as i install it the page transits to “rtl” ?
Did you use rudolf soultion ?
(I didn’t get what you were saying about the alternative soultion :expressionless: )

Toda mirosh :wink:


#15

I wrote my own solution which covered two stages:

  • build time - a watcher process monitors changes in the meteor build css
    and in turn generates an rtl version (i.e. Inverting all directional style
    ryles) of it. The generated file is placed in /public and is accessible
    from the browser

  • run time - the app has logic that inspects a specific client state (e.g
    user preferences) and accordingly decides whether to swap the meteor css
    file with the generated, that is disabling the former link tag and adding
    a new link tag referencing the latter.

As for the bootstrap rtl package you mentioned, i presume its simply the
rtl version of the bootstrap stylesheets wrapped in a meteor package.