BrowserSync / browser-sync

Keep multiple browsers & devices in sync when building websites. https://browsersync.io
https://discord.gg/2d2xUThp
Apache License 2.0
12.18k stars 757 forks source link

Does not work with <style> @import url("..."); </style> #10

Closed skh- closed 6 years ago

skh- commented 11 years ago

This is a great tool. However, it would be even better if it supported @import's of stylesheets.

I realize that including stylesheets this way is not optimal, but it does get around IE's limitation of 31 stylesheets, and is useful when in development - particularly with CMS's that include a lot of stylesheets.

When I downloaded this tool to try it out I was working on a Drupal project, which happens to do this until you turn on CSS aggregation. But at that point it also changes the name of the CSS files and caches them.

I took a look at modifying browser-sync-client.js but it seems like it's really only setup for altering <link> elements and ran short on time.

Thanks!

shakyShane commented 11 years ago

This is an interesting problem & not one I've even looked into.

It'll be low priority on the list of fixes for me, but i'll certainly look into this.

Also if you manage to get it work - even better :)

shakyShane commented 10 years ago

This is not currently on the roadmap, but you could trigger a full page refresh instead:

https://github.com/shakyShane/browser-sync/wiki/Working-with-a-Config-File#wiki-injectchanges---default-true

jorgegc commented 10 years ago

Hey guys,

I know the issue is closed but just for the record... I got it working by installing the Link CSS Drupal module. Here is the link if you want to check it out:

https://drupal.org/project/link_css

Cheers

shakyShane commented 10 years ago

How did that help? I'm guessing it creates <link> elements instead?

jorgegc commented 10 years ago

Yes, that is right. Drupal out of the box embeds CSS using @import so this module just forces Drupal to use <link> instead. I have written my own browsersync module for Drupal which takes care of that, I will put it up on Drupal.org soon.

jtomaszewski commented 9 years ago

You could leave that open though. Even if it's not a bug, definitely it's a missing feature not noted in README :<

Livereload has support not only for reloading @import url() stylesheets, but even also for images f.e. background-image:url(). We can see how it's done f.e. here: https://github.com/livereload/livereload-js/blob/master/src/reloader.coffee#L182-L198 .

We could extend codeSync.reload() function (https://github.com/shakyShane/browser-sync-client/blob/master/lib/code-sync.js#L117-L151) to also look for stylesheets in @import rules. But maybe because of performance we shouldn't parse all the stylesheets (in order to look for @import tags) in .reload() function, but in some other function and have those references cached somewhere. What do you think?

supermoos commented 9 years ago

+1 for this!

supermoos commented 9 years ago

Or at least at it to the readme :-)

fidelix commented 9 years ago

Should this really be closed? It would be a great feature!

SgtPooki commented 9 years ago

browser-sync start --server "." --files "**/*.*" --no-inject-changes

works perfectly for me.

shakyShane commented 9 years ago

@Fidelix - we are looking to add this feature in the future, yes.

@SgtPooki - that command cause a full reload per file-change, but this thread is actually about getting @import statements to cause CSS injection :)

SgtPooki commented 9 years ago

@shakyShane I didn't see the OP say anything about only wanting CSS injection, my bad. I figured others could benefit from some kind of working solution for now.

shakyShane commented 9 years ago

@SgtPooki - oh yeah, that's correct :)

Well either way, we'll be adding this In a way that allows css injection :)

tanc commented 9 years ago

Adding a note in the readme would have saved me hours of frustration. Although I should have just searched this issue queue to find this. Anyway, just a note in the readme as a starting point would really help new users (especially Drupal users) getting to grips with browser-sync.

gijsroge commented 9 years ago

A temp fix:

Place this in your template.php and it will generate link tags instead of @import's in your local environment.

function YOUR_THEME_css_alter(&$css) {
/**
   * Generate link tags instead of @import
   */
  $environment = variable_get('environment');
  if ($environment == 'development') {
    // Alter css to display as link tags.
    foreach ($css as $key => $value) {
      $css[$key]['preprocess'] = FALSE;
    }
  }
}
skh- commented 9 years ago

I have been using a similar one as mentioned by @gijsroge. Only difference is disabling @import based on the CSS aggregation setting (rather than the environment variable which isn't part of core).

/**
 * Implements hook_css_alter().
 *
 * Disables @import CSS tags for compatibility with BrowserSync.
 */
function HOOK_css_alter(&$css) {

  // Aggregation must be disabled.
  if (!variable_get('preprocess_css')) {

    // Disable @import on each css file.
    foreach ($css as &$item) {

      // Compatibility with disabling stylesheets in theme.info (263967).
      if (file_exists($item['data'])) {
        $item['preprocess'] = FALSE;
      }
    }
  }
}
iliakan commented 8 years ago

You probably could port the code for reloading url() and import from the chrome extension https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei

File livereload.js, see Reloader.prototype.reloadStyleImages, Reloader.prototype.reloadStylesheet and few other reload* methods.

Seems an easy and safe thing to do.

taivu commented 7 years ago

similar to @skh-'s temp fix , but for Drupal 8:

/**
 * Implements hook_css_alter().
 *
 * Disables @import CSS tags for compatibility with BrowserSync CSS injection while developing.
 */
function YOURTHEMENAME_css_alter(&$css) {

  // get value from settings/local.settings
  $is_css_preprocess = \Drupal::config('system.performance')->get('css')['preprocess'];

  // Aggregation must be disabled.
  if (!$is_css_preprocess) {

    // Disable @import on each css file.
    foreach ($css as &$item) {

      // Compatibility with disabling stylesheets in theme.info (263967).
      if (file_exists($item['data'])) {
        $item['preprocess'] = FALSE;
      }
    }
  }
}
pepelsbey commented 7 years ago

Here’s my use case: I have screen.css with a number of imports:

@import 'defaults.css';
@import 'fonts.css';
…

There are more nested imports in some files. And I don’t process my styles with anything to complie a single file, I just don’t need to. What I need is BS to watch files and push changes to browser. But only changes in screen.css propagate to browser. Changes in imported files detected too, but BS don’t push them.

That’s how I start watcher:

browser-sync start --server --no-notify --no-ui --files 'index.html, styles/**'

Is it even possible to properly push changes from imported files? Is there a workaround for that, apart from reloading the whole page? Thank you.

alvinpascoe commented 7 years ago

Thanks @taivu. I wrapped mine in a custom module, but it works great!