I'm creating a Blazor Mobile app, generated using "dotnet new mobileblazorbindings", and I want an editable title on my page.
I'm using Blazorise.Bootstrap in my app, and I am generating the title with the following line in my Razor file:
<TextEdit Plaintext="true" @bind-Text="Title" Class="h3"/>
which comes out as the following HTML:
<input id="<some_guff>" type="text" class="form-control-plaintext h3" value="My title text"></input>
(It's very nice that bootstrap contains classes .h1-.h6 which match headings h1-h6), which should make this a breeze...or so I thought...)
When I run the app with the default Bootstrap CSS as imported by the mobileblazorbindings template (wwwroot\css\bootstrap\bootstrap.min.css, which appears to be Bootstrap 4.3.1), this works perfectly - the text appears to be a heading, but clicking on it allows me to edit it.
If I try customising the Bootstrap using SASS and load my generated bootstrap CSS instead, it immediately stops working, and the input appears like a normal input.
I'm guessing there's something missing in my SASS build, but I've tried all sorts of things over the last few days and I cannot find it.
Here's my package.json:
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"private": true,
"workspaces": [
"bootstrap"
],
"dependencies": {
"bootstrap": "next",
"jquery": "^3.5.1",
"open-iconic": "^1.1.1",
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@popperjs/core": "^2.6.0",
"autoprefixer": "^10.2.1",
"babel-loader": "^8.2.2",
"babel-preset-es2015-ie": "^6.7.0",
"css-loader": "^5.0.1",
"mini-css-extract-plugin": "^1.3.3",
"node-gyp": "^7.1.2",
"node-sass": "^5.0.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.2.4",
"postcss-cli": "^8.3.1",
"sass-loader": "^10.1.0",
"style-loader": "^2.0.0",
"webpack": "^5.12.2",
"webpack-cli": "^4.3.1"
},
"scripts": {
"css-deploy": "npm run css-build && npm run css-postcss",
"css-build": "node-sass app.scss dist/app.css",
"css-postcss": "postcss --use autoprefixer --output dist/app.css dist/app.css",
"css-watch": "npm run css-build -- --watch",
"deploy": "npm run css-deploy && npm run js-build",
"js-build": "babel _javascript --out-dir lib",
"js-watch": "npm run js-build -- --watch",
"start": "npm-run-all css-watch js-watch"
}
}
Here's my bootstrap-customisation.scss:
/* Import the open-iconic icons */
@import "../node_modules/open-iconic/font/css/open-iconic-bootstrap.min.css";
/* Required */
@import "bootstrap/scss/_functions";
@import "bootstrap/scss/_variables";
@import "bootstrap/scss/_mixins";
// Modify variables here
/* Standard bootstrap imports */
@import "bootstrap/scss/_root";
@import "bootstrap/scss/_reboot";
@import "bootstrap/scss/_type";
@import "bootstrap/scss/_images";
@import "bootstrap/scss/_code";
@import "bootstrap/scss/_grid";
@import "bootstrap/scss/_tables";
@import "bootstrap/scss/_forms";
@import "bootstrap/scss/_buttons";
@import "bootstrap/scss/_transitions";
@import "bootstrap/scss/_dropdown";
@import "bootstrap/scss/_button-group";
@import "bootstrap/scss/_input-group";
@import "bootstrap/scss/_custom-forms";
@import "bootstrap/scss/_nav";
@import "bootstrap/scss/_navbar";
@import "bootstrap/scss/_card";
@import "bootstrap/scss/_breadcrumb";
@import "bootstrap/scss/_pagination";
@import "bootstrap/scss/_badge";
@import "bootstrap/scss/_jumbotron";
@import "bootstrap/scss/_alert";
@import "bootstrap/scss/_progress";
@import "bootstrap/scss/_media";
@import "bootstrap/scss/_list-group";
@import "bootstrap/scss/_close";
@import "bootstrap/scss/_toasts";
@import "bootstrap/scss/_modal";
@import "bootstrap/scss/_tooltip";
@import "bootstrap/scss/_popover";
@import "bootstrap/scss/_carousel";
@import "bootstrap/scss/_spinners";
@import "bootstrap/scss/_utilities";
@import "bootstrap/scss/_print";
And here's my root app.scss:
/* Source SASS file to build custom Bootstrap site file */
@import "bootstrap-customisation";
/* App-specific customizations */
@import "mystyles.scss";
where mystyles.scss currently contains the original contents of app.css as autogenerated.
I am building my app.css using yarn run css-deploy
and then manually copying the generated dist\app.css to wwwroot\css\app.css
When I run the app now, it's almost there, but there are two things missing:
I've been bashing my head off this brick wall for the past week, trying all sorts of different ways of building Bootstrap, but I haven't been able to find what's missing. It feels like this should be trivial, but it just doesn't work, which makes me worry about any other customisation I might do to Bootstrap.
Things I've tried:
Any help or pointers very gratefully received.
Thanks in advance,
Ian
Okay, I've found what the problem was. Ultimately I was looking in the wrong place. It came down to a CSS class ordering problem rather than any sort of build problem.
Remember my input control:
<input id="<some_guff>" type="text" class="form-control-plaintext h3" value="My title text"></input>
Digging into the bootstrap source code, class .form-control-plaintext is defined in _forms.scss, and .h3 is defined in _type.scss.
Now look at my bootstrap imports:
/* Standard bootstrap imports */
@import "bootstrap/scss/_type";
...
@import "bootstrap/scss/_forms";
_type (with .h3) comes before _forms (with .form-control-plaintext), so the definitions of the .form-control-plaintext class take priority over those of .h3. Moving the _type line to the end of the list of imports solved it:
/* Standard bootstrap imports */
...
@import "bootstrap/scss/_forms";
...
@import "bootstrap/scss/_type";
Now class .h3 is defined after .form-control-plaintext so it takes priority, and all works perfectly. I have an input which looks like a header.