This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Load CSS in webpack with style-loader and css-loader - #330

Merged
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets
Nov 8, 2018
Merged

Load CSS in webpack with style-loader and css-loader#330
valentijnnieman merged 1 commit into
masterfrom
load_stylesheets

Conversation

@valentijnnieman

@valentijnniemanvalentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
Contributor

@chriddyp Here's a little test to see what happens in Percy when we load the CSS using Webpack plugins style-loader and css-loader. These plugins take the CSS we require in JS using import './filename.css'; and injects it into the HTML.

Edit: as talked about in #312

@valentijnnieman

valentijnnieman commented Oct 15, 2018

Copy link
Copy Markdown
ContributorAuthor

Ok, that does do something. I guess to really know if this is a suitable solution I'd need to also add the react-virtualized@9.9.0 CSS file (which I didn't yet because I wasn't sure which components use that), and make sure they are imported in the correct component. @chriddyp Can you help with that?

@chriddyp

Copy link
Copy Markdown
Member

react-virtualized@9.9.0 the Dropdown component uses this one

@valentijnnieman

Copy link
Copy Markdown
ContributorAuthor

Alright, well, the Percy snapshots show it's working. They just look a little odd. Will check it out more tomorrow!

@chriddyp

Copy link
Copy Markdown
Member

Note that we'll always have some artifacts in the rendering. Percy needs for all of the styles to be present on the page (in the actual DOM) so if any of the components update the styles through JS in a way that doesn't persist the styles inline (i.e. the style is only in memory), then the styles won't appear in the image diff (since percy just downloads the HTML on the page).

For example, these icons in the corner are from plotly.js's modebar. If you inspect-element these icons, you'll see that their styles aren't persisted in the SVG in the DOM, and so in the screenshot they're just jumbled in the corner.

image

@valentijnnieman

valentijnnieman commented Oct 16, 2018

Copy link
Copy Markdown
ContributorAuthor

@chriddyp Interesting, I always wondered about those icons in the corner :) in this setup, style-loader injects the CSS into the <head> tag, but I'm not sure at which point that's being done.

if you run the gallery test as a standalone Dash app, it still looks different from the Percy snapshots.

here's the gallery as a Dash app code for convenience:
from textwrap import dedent
import json
from datetime import datetime
from textwrap import dedent as d
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Upload'),
dcc.Upload(),
html.Label('Horizontal Tabs'),
dcc.Tabs(id="tabs", children=[
dcc.Tab(label='Tab one', className='test', style={'border': '1px solid magenta'}, children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
], id='tab-one'),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
],
style={
'fontFamily': 'system-ui'
},
content_style={
'border': '1px solid #d6d6d6',
'padding': '44px'
},
parent_style={
'maxWidth': '1000px',
'margin': '0 auto'
}
),
html.Label('Vertical Tabs'),
dcc.Tabs(id="tabs1", vertical=True, children=[
dcc.Tab(label='Tab one', children=[
html.Div(['Test'])
]),
dcc.Tab(label='Tab two', children=[
html.Div([
html.H1("This is the content in tab 2"),
html.P("A graph here would be nice!")
])
]),
dcc.Tab(label='Tab three', children=[
html.Div([
html.H1("This is the content in tab 3"),
])
]),
]
),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL',
id='dropdown'
),
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value=['MTL', 'SF'],
multi=True
),
html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
value='MTL'
),
html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'},
{'label': u'北京', 'value': u'北京'}
],
values=['MTL', 'SF']
),
html.Label('Text Input'),
dcc.Input(value='', placeholder='type here', type='text',
id='textinput'),
html.Label('Disabled Text Input'),
dcc.Input(value='disabled', type='text',
id='disabled-textinput', disabled=True),
html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i)
for i in range(1, 6)},
value=5,
),
html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}],
'layout': {
'title': u'北京'
}
}
),
html.Label('DatePickerSingle'),
dcc.DatePickerSingle(
id='date-picker-single',
date=datetime(1997, 5, 10)
),
html.Label('DatePickerRange'),
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime(1997, 5, 3),
end_date_placeholder_text='Select a date!'
),
html.Label('TextArea'),
dcc.Textarea(
placeholder='Enter a value... 北京',
style={'width': '100%'}
),
html.Label('Markdown'),
dcc.Markdown('''
#### Dash and Markdown
Dash supports [Markdown](http://commonmark.org/help).
Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
北京
'''.replace(' ', '')),
dcc.Markdown(['# Line one', '## Line two']),
dcc.Markdown(),
dcc.SyntaxHighlighter(dedent('''import python
print(3)'''), language='python'),
dcc.SyntaxHighlighter([
'import python',
'print(3)'
], language='python'),
dcc.SyntaxHighlighter()
])
if __name__ == '__main__':
app.run_server(debug=True)

@wbrgss Do you have any insights into what's going on here?

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Oct 29, 2018

Copy link
Copy Markdown
Contributor

@valentijnnieman Looks good to me now that I know webpack.config.js already has a rule for css files!
Can you confirm that the percy visual changes are all as expected?

As for when the styles get loaded, except if you have lazy execution, they should be loaded into the DOM shortly after the bundle was added as the entire dependency chain will be evaluated upon download by the browser.

@valentijnniemanvalentijnnieman changed the title [WIP] Load CSS in webpack with style-loader and css-loaderLoad CSS in webpack with style-loader and css-loaderNov 7, 2018

@wbrgsswbrgss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a clean and sensible import pattern that makes a net improvement to the Percy diffs, so 💃 from me. Especially as style-loader and css-loader are already there, as @Marc-Andre-Rivet pointed out.

@wbrgss

Copy link
Copy Markdown
Contributor

I'd like to get @chriddyp's thoughts on standardising this pattern. To quote a comment in #312:

If we figure how to do this, then I'd like to make it a standard so that this repo is following our own conventions. That is, I'd like for us to update our other repos with the same system, our dash-component-boilerplate project, and our plugin documentation.

@wbrgss
wbrgssforce-pushed the load_stylesheets branch 2 times, most recently from 95794bf to 6581c37CompareNovember 7, 2018 21:29
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
Load CSS in webpack with style-loader and css-loader
Remove external css_dist refs to moved css files
Add react-virtualized css to Dropdown and remove css_dist dep
Version bump to 0.38.0
@valentijnnieman
valentijnnieman merged commit 35dc2e5 into masterNov 8, 2018
@valentijnnieman
valentijnnieman deleted the load_stylesheets branch November 8, 2018 14:56
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@valentijnnieman@chriddyp@Marc-Andre-Rivet@wbrgss