Bootstrapをdivのスコープのみに制限するにはどうすればよいですか?ExtJSアプリ内に特定のdiv用のBootstrapスタイルシートをネストする必要がありますが、独自の本体、ul、li、aなどが必要なため、両方が衝突しています。
簡単に更新できるように、bootstrap.cssを手動で編集する(または最小限に抑える)ことを避けようとしています。
Bootstrapをdivのスコープのみに制限するにはどうすればよいですか?ExtJSアプリ内に特定のdiv用のBootstrapスタイルシートをネストする必要がありますが、独自の本体、ul、li、aなどが必要なため、両方が衝突しています。
簡単に更新できるように、bootstrap.cssを手動で編集する(または最小限に抑える)ことを避けようとしています。
ブートストラップ リポジトリをフォークして、bootstrap.less
ブートストラップ スタイルをラップするように変更できます。
.bootstrap-scope {
//put bootstrap @includes in here
}
次に、ブートストラップ プロジェクトのルートで、実行make
してファイルを生成しbootstrap.css
ます。
body タグと html タグに割り当てられたグローバル スタイルのブートストラップは失われますが、いずれにしても必要ない場合があります。
次に、アプリで、必要なコンテナーに.bootstrap-scope
クラスを指定します。
less/bootstrap.less を変更した結果が私にとって十分ではなかったため (投稿の下部にある理由を参照)、最終的には bootstrap.css をフィルタリングしました。
var css = require('css'), fs = require('fs');
var prefix = '.bootstrap-scope';
var inFile = 'bootstrap.css';
var cssAst = css.parse(fs.readFileSync(inFile, 'utf8'));
prefixNode(cssAst);
console.log(css.stringify(cssAst));
function prefixSelector(sel){
if (sel.match(/^@/)) return sel;
var m = sel.match(/(^| )(body|html)($|\W.*)/i);
if (m)
return m[1] + prefix + m[3];
else
return prefix + ' ' + sel;
}
function prefixNode(node) {
if (node.selectors) {
node.selectors = node.selectors.map(prefixSelector);
} else if (node.stylesheet) {
node.stylesheet.rules.forEach(prefixNode);
} else if (node.rules) {
node.rules.forEach(prefixNode);
}
}
bootstrap.css が生成されるため、盲目的に実行することもできます (Alexey のソリューションに似ていますが、いくつかのコーナー ケースも処理します)。
perl -lpe 'BEGIN { $prefix = ".bootstrap-scope" } if (($indent, $s, $sep) = /^(\s*)([^@\s].*?)(\s*[,{])$/) { $s =~ /^(from|to)*$/ or $s =~ s/(^| )(body|html)($|\W.*)/$1$prefix$3/i or $s = "$prefix $s"; $_ = "$indent$s$sep" }' bootstrap.css
less/bootstrap.css を変更し、grunt を呼び出して dist/css/bootstrap.css (Andrew Homeyer のソリューション) を生成することに関しては、いくつかのケースでは (少なくともブートストラップ 3 では) うまく機能していないようです:
.make-grid-columns (less/mixins.xml から) のようなさまざまな mixin は、不適切なプレフィックスが付けられてしまいます。例:
.bootstrap-scope .col-sm-1,
.col-sm-2,
.col-sm-3,
LESS での「&」の使用は制限されています。
.caret {
.btn-default & {
になる
.btn-default .bootstrap-scope .caret {
私たちが望むものの代わりに:
.bootstrap-scope .btn-default .caret {
この正当な要件を達成するためのはるかに簡単な方法があります: }NEWLINE と ,NEWLINE を以前の値とクラス スコープに置き換えます。たとえば Sublime では非常に簡単です。
選択}\r\n
Alt + F3 (すべてのオカレンスを選択)
}\r\n.bootstrap-scope に置き換えます
を選択、\r\n
Alt + F3 (すべてのオカレンスを選択)
,\r\n.bootstrap-scope に置き換えます
それでおしまい!交換には約1分かかるため、今後の更新は非常に簡単です。私の答えが役に立てば幸いです。
外部ライブラリが関与しない純粋な JavaScript ソリューションが必要な場合は、次の方法を使用できます。一般的な考え方は、生の css をロードし、必要に応じてスコープ セレクターを追加して行ごとに解析することです。
function scopeCSS(scopeSelector, rawCSS) {
return rawCSS.split('\n').map(line => {
var trimmedLine = line.trim()
if (trimmedLine.startsWith('*') || trimmedLine.startsWith('/*') || trimmedLine.startsWith('@media') || trimmedLine === '' || trimmedLine.endsWith(';') || trimmedLine.endsWith('}')) {
return line
}
return line.split(',').map(selector => selector.trim()).map(selector => selector === '' ? selector : `${scopeSelector} ${selector}`).join(',');
}).join('\n')
}
const rawCSS = document.querySelector('#before').textContent // just as an example, you'd probably use a raw loader with webpack
document.querySelector('#after').textContent = scopeCSS('.bootstrap-scope', rawCSS)
#grid {
display: grid;
width: 100%;
grid-template-columns: 1fr 1fr;
}
<div id="grid">
<div id="col-1">
<pre id="before">/*!
* Bootstrap Grid v5.0.0-alpha1 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
.container,
.container-fluid,
.container-sm,
.container-md,
.container-lg,
.container-xl,
.container-xxl {
width: 100%;
padding-right: 1rem;
padding-left: 1rem;
margin-right: auto;
margin-left: auto;
}
@media (min-width: 576px) {
.container, .container-sm {
max-width: 540px;
}
}
@media (min-width: 768px) {
.container, .container-sm, .container-md {
max-width: 720px;
}
}
@media (min-width: 992px) {
.container, .container-sm, .container-md, .container-lg {
max-width: 960px;
}
}
@media (min-width: 1200px) {
.container, .container-sm, .container-md, .container-lg, .container-xl {
max-width: 1140px;
}
}
@media (min-width: 1400px) {
.container, .container-sm, .container-md, .container-lg, .container-xl, .container-xxl {
max-width: 1320px;
}
}
.row {
--bs-gutter-x: 1.5rem;
--bs-gutter-y: 0;
display: flex;
flex: 1 0 100%;
flex-wrap: wrap;
margin-top: calc(var(--bs-gutter-y) * -1);
margin-right: calc(var(--bs-gutter-x) / -2);
margin-left: calc(var(--bs-gutter-x) / -2);
}
.row > * {
box-sizing: border-box;
flex-shrink: 0;
width: 100%;
max-width: 100%;
padding-right: calc(var(--bs-gutter-x) / 2);
padding-left: calc(var(--bs-gutter-x) / 2);
margin-top: var(--bs-gutter-y);
}
.col {
flex: 1 0 0%;
}
/*# sourceMappingURL=bootstrap-grid.css.map */</pre>
</div>
<div id="col-2">
<pre id="after"></pre>
</div>
</div>