Как при использовании SASS импортировать файл из другого каталога?

93

Можно ли в SASS импортировать файл из другого каталога? Например, если бы у меня была такая структура:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

template.scss может импортировать _common.scss с помощью, @import "common"но возможно ли для more_styles.scss импортировать _common.scss? Я попробовал несколько различных вещей , в том числе @import "../sub_directory_a/common"и , @import "../sub_directory_a/_common.scss"но ничего не похоже на работу.

spaaarky21
источник

Ответы:

69

Похоже, некоторые изменения в SASS сделали возможным то, что вы изначально пытались сделать:

@import "../subdir/common";

Мы даже заставили это работать для какой-то совершенно несвязанной папки, расположенной в c:\projects\sass:

@import "../../../../../../../../../../projects/sass/common";

Просто добавьте достаточно, ../чтобы быть уверенным, что вы окажетесь в корне диска, и все готово.

Конечно, это решение далеко не красивое, но я не мог получить импорт из совершенно другой папки для работы, не используя и I c:\projects\sassне устанавливая переменную среды SASS_PATH(из ссылки:: load_paths ) на то же значение.

Оливер
источник
9
Это «далеко не красиво»! Но этот ответ набирает много голосов. Это действительно считается лучшей практикой, чем -I? Если этот путь изменится, придется много искать и заменять; и для этого требуется та же структура локальных папок, что и у всех, кто использует .scss
WiseOldDuck
14
«Просто добавьте достаточно ../, чтобы быть уверенным, что вы окажетесь в корне диска, и все готово». Хахаха, это сделало мой день.
Стив Харрисон
4
Я советую полностью игнорировать этот ответ. К сожалению, это один из многих вопросов SO, на который при голосовании «за» неправильно отвечают. Если вы хотите, чтобы ваш код легко ломался, используйте его. Если вам нужно надежное решение, см. Мой ответ ниже.
adi518
2
@ adi518: Я мог бы поспорить с вашим утверждением: «Если вы хотите, чтобы ваш код легко ломался, используйте его». Данное решение работает у нас с тех пор (то есть уже почти 4 года) и ничего не сломало. Я считаю, что это одно из тех решений, которое может быть несколько грязным, но позволяет выполнять работу быстро и без необходимости слишком глубоко копаться во внутренностях некоторых задействованных инструментов.
Оливер
2
Серьезно не делай этого.
shinzou 09
34

Вы можете использовать -Iпереключатель командной строки или :load_pathsпараметр из кода Ruby для добавления sub_directory_aв путь загрузки Sass. Итак, если вы используете Sass root_directory, сделайте что-нибудь вроде этого:

sass -I sub_directory_a --watch sub_directory_b:sub_directory_b

Тогда вы можете просто использовать @import "common"в more_styles.scss.

Миикка
источник
1
Отлично. Это именно то, что я хотел знать. И я думаю, что Мистер Джек тоже что-то замечает, но похоже, что у Compass просто есть папка, которая уже находится на пути.
spaaarky21 05
3
Цепные -I флаги для включения более одного каталога, напримерsass -I sub_directory_a -I sub_directory_c --watch sub_directory_b:sub_directory_b
bob esponja
20

Используя webpack с sass-loader, я могу ~ссылаться на корневой путь проекта. Например, при условии, что структура папок OPs находится в файле внутри sub_directory_b:

@import "~sub_directory_a/_common";

Документация: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules

Самми
источник
8
Кажется, это импортируется из node_modules/корня проекта, а не из него.
Splaktar
Мне пришлось добавить "sub_directory_a"к моему includePathsи использовать @import "common";синтаксис при использовании Angular CLI, который включает sass-loader.
Splaktar
Это должен быть утвержденный ответ.
shinzou 09
4
Согласен со Сплактаром. Из документации sass-loader: webpack предоставляет расширенный механизм для разрешения файлов. Загрузчик sass использует функцию настраиваемого импортера Sass для передачи всех запросов механизму разрешения веб-пакетов. Таким образом, вы можете импортировать свои модули Sass из node_modules. Просто добавьте к ним ~, чтобы сообщить webpack, что это не относительный импорт ... Важно добавлять только ~, потому что ~ / разрешается в домашний каталог.
Энтони
Обратите внимание, что ~/это, похоже, не относится к домашнему каталогу для меня. Или любой каталог, который я пытался проверить. Есть ли способ на самом деле попытаться выяснить, к чему это относится?
Дуглас Гаскелл
8

Импорт .scssфайла, который имеет вложенный импорт с другой относительной позицией, работать не будет. верхний предлагаемый ответ (с использованием большого количества ../) - это просто грязный хакер, который будет работать, пока вы добавите достаточно, ../чтобы добраться до корня ОС развертывания вашего проекта.

  1. Добавьте целевой путь SCSS в качестве цели поиска для компилятора SCSS. Этого можно добиться, добавив папку таблиц стилей в файл конфигурации scss, это функция используемой вами структуры,

использовать :load_pathsв config.rdдля каркасов на основе компаса (например, рельсы)

используйте следующий код scss-config.jsonдляfourseven/meteor-scss

{
  "includePaths": [
    "{}/node_modules/ionicons/dist/scss/"
  ]
}
  1. Используйте абсолютные пути (а не относительные пути).

Пример, с fourseven/meteor-scss, вы можете использовать, {}чтобы выделить верхний уровень вашего проекта, как показано в следующем примере.

@import "{}/node_modules/module-name/stylesheet";
helcode
источник
Ничего особенного meteor, это был просто пример.
helcode
4

Выбранный ответ не предлагает жизнеспособного решения.

Практика OP кажется нерегулярной. Общий / общий файл обычно находится partialsв стандартном шаблонном каталоге. Затем вам следует добавить partialsкаталог в пути импорта конфигурации, чтобы разрешить частичные данные в любом месте вашего кода.

Когда я впервые столкнулся с этой проблемой, я подумал, что SASS, вероятно, предоставляет вам глобальную переменную, аналогичную переменной Node __dirname, которая хранит абсолютный путь к текущему рабочему каталогу ( cwd). К сожалению, это не так, и причина в том, что интерполяция на@import директивы невозможна, поэтому вы не можете использовать динамический путь импорта.

Согласно документам SASS .

Вам нужно установить :load_pathsв вашей конфигурации Sass. Поскольку OP использует Compass, я буду следовать этому в соответствии с документацией здесь .

Вы можете использовать решение CLI по назначению, но почему? его гораздо удобнее добавлять config.rb. Было бы разумно использовать CLI для переопределенияconfig.rb (например, различные сценарии сборки).

Итак, если вы config.rbнаходитесь в корневом каталоге проекта, просто добавьте следующую строку: add_import_path 'sub_directory_a'

И теперь @import 'common';будет нормально работать где угодно.

Хотя это отвечает на OP, есть еще кое-что.

Приложение

Вы, вероятно, столкнетесь со случаями, когда вы хотите импортировать файл CSS встроенным способом, то есть не через стандартную @importдирективу, которую CSS предоставляет из коробки, а фактическое слияние содержимого файла CSS с вашим SASS. Есть еще один вопрос , на который нет однозначного ответа (решение не работает в кросс-среде). Тогда решение - использовать это расширение SASS.

После установки добавьте в конфигурацию следующую строку: require 'sass-css-importer'а затем где-нибудь в своем коде:@import 'CSS:myCssFile';

Обратите внимание, что расширение должно быть опущено, чтобы это работало.

Однако мы столкнемся с той же проблемой при попытке импортировать файл CSS по пути, отличному от пути по умолчанию, и add_import_pathне учитывать файлы CSS. Итак, чтобы решить эту проблему, вам нужно добавить еще одну строку в вашу конфигурацию, которая, естественно, похожа:

add_import_path Sass::CssImporter::Importer.new('sub_directory_a')

Теперь все будет работать нормально.

PS, я заметил, что в sass-css-importerдокументации указано, что CSS:в дополнение к отсутствию .cssрасширения требуется префикс . Я обнаружил, что это работает независимо. Кто-то завел вопрос , на который пока нет ответа.

adi518
источник
2

Gulp выполнит работу по просмотру ваших файлов sass, а также добавит пути к другим файлам с помощью includePaths. пример:

gulp.task('sass', function() {
  return gulp.src('scss/app.scss')
    .pipe($.sass({
      includePaths: sassPaths
    })
    .pipe(gulp.dest('css'));
});
ошрийский сбор
источник
7
Вы ведь понимаете, что includePaths просто использует -Iпараметр из командной строки, верно?
cimmanon
2

node-sass(официальная оболочка SASS для node.js) предоставляет параметр командной строки, --include-pathпомогающий с такими требованиями.

Пример:

В package.json:

"scripts": {
    "build-css": "node-sass src/ -o src/ --include-path src/",
}

Теперь, если у вас есть файл src/styles/common.scssв вашем проекте, вы можете импортировать его в @import 'styles/common';любом месте вашего проекта.

См. Https://github.com/sass/node-sass#usage-1 .

Виджей Аггарвал
источник
1

Чтобы определить файл для импорта, можно использовать общие определения всех папок. Вы просто должны знать, что это относительно файла, который вы определяете. Подробнее о возможности импорта с примерами вы можете узнать здесь .

Неша Зорич
источник
1

При использовании веб-компилятора в Visual Studio вы можете добавить путь к includePathcompilerconfig.json.defaults. Тогда нет необходимости в некотором количестве, ../поскольку компилятор будет использовать includePath в качестве местоположения для поиска импорта.

Например:

"includePath": "node_modules/foundation-sites/scss",
ДавГарсия
источник
0

Это половинный ответ.

Обратите внимание на Compass , с его помощью вы можете поместить свой файл _common.scssв partialsпапку, а затем импортировать его @import common, но он работает с каждым файлом.

Алессандро Вендрусколо
источник
Я думаю, что ответ Миикки действительно был тем, что мне было нужно, но теперь мне тоже интересно узнать о Compass. Каталог partials как-то специфичен для конкретного проекта? Или файлы, помещенные в каталог partials, будут доступны «глобально» везде, где используется Compass?
spaaarky21 05
4
Это вообще не отвечает на вопрос.
cimmanon
0

Я столкнулся с той же проблемой. Из моего решения я пришел к этому. Итак, вот ваш код:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

Насколько я знаю, если вы хотите импортировать один scss в другой, он должен быть частичным. Когда вы импортируете из другого каталога, назовите ваш more_styles.scssв _more_styles.scss. Затем импортируйте его в свой template.scss@import ../sub_directory_b/_more_styles.scss. У меня это сработало. Но, как вы упомянули, ../sub_directory_a/_common.scssне работает. Это тот же каталог, что и template.scss. Вот почему это не сработает.

Саджидур Рахман
источник
0

Лучше всего использовать sass-loader. Он доступен как пакет npm. Он решает все проблемы, связанные с путями, и делает его очень простым.

Рут Шах
источник
-6

У меня была такая же проблема, и я нашел решение, добавив путь к файлу, например:

@import "C: / xampp / htdocs / Scss_addons / Bootstrap / bootstrap";

@import "C: / xampp / htdocs / Scss_addons / Compass / compass";

Netix
источник
1
Хотя аналогичный ответ был дан ранее, абсолютный путь зависит от конкретного сервера в качестве общего ответа (вы, конечно, сказали «нравится»).
dakab