How can I override CSS styles in GWT/Bootstrap? - css

I just started to port twitter's bootstrap to GWT (see the github project here and a very ugly demo here), but, I was having a log of issues with bootstrap styles vs Gwt styles.
Bootstrap put a border-top in tr/td elements, and GWT components basically use tables everywhere. In the demo you can see that bug in the left VerticalPanel.
So, I was looking for a way to make GWT components ignore bootstrap styles, and I have no idea how to do this.
Is there a simple way to make it work right?
Thanks in advance.

It's possible, but somewhat complex to do something with a Linker in GWT. The high-level idea would be:
Put all your GWT components in a <div id="gwt">...</div>
Add a linker to the GWT Module file that will process CSS files.
In the linker, transform the GWT CSS (e.g., standard.css) to insert a #gwt before each selector rule.
The first part is easy, just add an id to your root element.
The second part is also easy, simply add code that looks like this to your Module.gwt.xml file:
<define-linker name="cssLinker" class="com.you.bootstrap.linker.CssRenamingLinker" />
<add-linker name="cssLinker"/>
The hard part is implementing the Linker. It's possible to do parse it by hand, but you might find it easier to use something like SAC.
Using the Linker, you can transform your CSS by inserting a #gwt before each selector. Using SAC, you might do that by overriding all the DocumentHandler methods to simply emit each of their arguments to an OutputStream. In DocumentHandler.startSelector() you would first emit "#gwt " before each selector.
[Edit]
This assumes that GWT's standard.css defines styles that override the bootstrap styles. If not, you might have to 'enhance' the GWT CSS with defaults. There's a list of W3C recommended defaults here.
The benefit is that this is future-resistant - if GWT styles change or if bootstrap styles change, this should be robust.
Hope that helps,
Adam

You can simply add a style to one of your root GWT objects and then simply override the bootstrap styles to remove those messy borders:
<div class="gwt">
... some other GWT-content
</div>
and in your CSS:
.gwt tr, .gwt td {
border-top: 0px;
}
Of course if you need to embed some bootstrap elements in your GWT elements then you will have to hack around and do:
<div class="gwt">
... some other GWT-content
<div class="bootstrap">...
... Bootstrap elements
</div>
</div>
and in your CSS:
.bootstrap tr, .bootstrap td {
border-top: 1px; // Whatever bootstrap style puts
}

Related

Bootstrap 4 - CSS without any global styles

I'm developing a small control which is directly embedded in a parent page (without iFrame).
My control is written using react-bootstrap, so the bootstrap4 css is also embedded along with my control.
While developing my app as standalone, everything was fine.
After embedding it however, it turns out that there are some "global" bootstrap styles, such as the so called "list-styles" that don't get applied only on HTML elements having bootstrap classes, but instead on any matching HTML tag.
This causes the parent page's layout to get scrambled once my control is loaded.
Examples for bootstrap classes that are applied globally and which cause problems for me are styles like these which can be found in the bootstrap4 default css:
dl, ol, ul {
margin-top: 0;
margin-bottom: 1rem;
}
or
label {
display: inline-block;
margin-bottom: .5rem;
}
This is very unfortunate for my use case. Is there a way for getting rid of any styles in bootstrap, which are not linked to any proper css bootstrap class? I don't want any styling of HTML tags that are not explicitly linked to a bootstrap class.
Thanks for your help.
I can think of three options, though I'm not sure they will do for you:
Paste Bootstrap's styles into a local file (instead of getting them from a CDN or something) and delete what you don't want (most of the unwanted styles should be at the top of the file)
Look for another, more minimal version of Bootstrap. I don't know if such versions/customizations exist but they very well might
Don't use Bootstrap. You can just as easily write your own css lines (personally I find that Bootstrap makes you lose control over your styling, but that's my opinion)

How to refer to an Angular component's full template setting CSS without referring to any tags?

My usual setup for each view is an outer DIV that I style as the base background etc.
<div class="outer">
<!-- Actual stuff in here -->
</div>
Then, in the SASS, I refer to it like so.
div.outer { ... }
That adds one lever of indent and seems like an unnecessary (though minor) increment in complexity. So I wonder if it's possible to add a style to the template itself. Partly, to lower the complexity. Partly, because I'm going to have text-only elements with no tags at all.
Is it possible to set the style of template from SASS files if there are no tags, only text in it?
You can apply styling to the component host element with the :host selector:
:host {
color: red;
}
See this stackblitz for a demo.

Applying a Stylesheet Within One Div Only

I have a site I am adding some functionality to. The site is a bit outdated but I am not being paid to overhaul the entire site, just a few pages. Because of this I am using more modern code on these pages but there is still old code on these pages. Because of the old code (which will stay and not be removed) I have some CSS that conflicts.
Is it possible to make an entire stylesheet only apply to styles within a div.
Example:
<div class="style-sheet-modern">
<!-- My Stylesheet applies only within this div -->
</div>
My first thought was to just rename my css to fall within the div. Example:
.style-sheet-modern .conflicting-class{ /* styles */ }
However, this isn't desirable because there are a few hundred lines of CSS and I don't want to go through and rename all of my CSS. Also makes it difficult to update in the future.
Is there a way to apply an entire stylesheet within a certain div and not anywhere else on the page?
Sure, in most modern browsers. Put a scoped stylesheet WITHIN the div.
<div class="style-sheet-modern">
<style scoped>
.conflicting-class { ... }
</style>
</div>
You can use #import to use external styles. Note, for browsers that don't support it, it will apply the style to the entire page. So you probably just want to add an id to the div you want and style with that, for compatibility.
Why not give the <div> an ID?
Then you could use specificity to override just the classes/ids that are in that div?
IE:
<div id="style-sheet-modern">
<div class="my-class"></div>
<div class="etc"></div>
</div>
You could then target all styles inside the "modern" div like this:
#style-sheet-modern .my-class{
color:black;
}
#style-sheet-modern .etc {}
There would be no browser support issues.
If you're using something like less or sass – you could even have it in a separate file named "style-sheet-modern.less" or whatever you want it named and #import it at the bottom of your main styles file. This include would need to come last in the file so that it will override the other styles that could be applied to those same styles.
You could use a wildcard to reset all the styles inside the #style-sheet-modern as well if necessary like this:
#style-sheet-modern * {
reset: stuff; //obviously not the actual css
}
That reset for those styles would be the first thing in your 'style-sheet-modern.*ss' file.
And as I mentioned before, no browser support issues.

How to use sass to properly avoid embedding twitter bootstrap class names on HTML

I am working on a Rails project that is just starting. We want to use twitter bootstrap as a base for our styles, at the beginning we would simply use bootstrap's class names directly on the HTML code, just like is shown in bootstrap's documentation, but after reading the following posts:
Lessons learned in maintainable css
Please stop embedding Bootstrap classes in your HTML
it became clear why that's not the proper why to use bootstrap, so after some more readings:
Decouple Your CSS From HTML
smacss
among other, it seemed that using sass #extend was the proper way to avoid using bootstrap's class names, so instead of doing this:
<button type="submit" class="btn">Search</button>
we would do this:
<button type="submit" class="button">Search</button>
and our sass code would look like this:
.button {
#extend ".btn";
}
The problem with that approach, besides the bunch of extra selectors that will be added each time we extend a bootstrap class just to use a different name, is that in cases where bootstrap uses selectors like this:
.form-search .input-append .btn, .form-search .form-input-append .btn {
border-radius: 0 14px 14px 0;
}
the button won't get the right style because sass will not apply that same rule to our custom class name, I mean, sass is not doing this:
.form-search .input-append .btn, .form-search .input-append .button,
.form-search .form-input-append .btn, .form-search .form-input-append .button {
border-radius: 0 14px 14px 0;
}
So I wonder, is this the right way to avoid embedding bootstrap's class names into HTML, if so, how should I handle this problem (it happens frequently)? if not, what would be a better way to use custom class names but still get the styles from bootstrap.
I really appreciate your thoughts on this. Please keep in mind that I am just learning about overall web design (css, sass, less, html, js, etc.).
When you rename .btn to .button, you also should rename .form-search to .form-searchnew etc?
In that case your sass code in the example above should be something like:
.form-searchnew .input-appendnew .button {
extend(.form-search .input-append .btn);
}
Which make sense (i don't know sass) and results in the css you expect.
I think bootstrap is not about css only. Bootstrap is about css, html(structure) and javascript. Even when you separate css from html i would not easy to migrate to an other framework. Beside the css you will have to change the html structure and javascript call too.
Example migrate from Twitter's Bootstrap 2 to 3 (see: Updating Bootstrap to version 3 - what do I have to do?). I also wondered if you could migrate by extending the old classes to the new css (see: http://bassjobsen.weblogs.fm/migrate-your-templates-from-twitter-bootstrap-2-x-to-twitter-bootstrap-3/). After reading the migration guide, i think you couldn't.
Other solutions. Angular JS decouples Twitter's Bootstrap from javascript. Also in this case migrations does not seem to be painless see: Angular Dialog directives with Bootstrap 3
Maybe also read this post: http://www.jasonwong.org/post/45849350459/migrating-from-zurb-foundation-twitter-bootstrap-to. It refers to Bourdon and Neat.
Example from their website:
<!-- HTML markup for the section right below this code block -->
<section>
<aside>What is it about?</aside>
<article>Neat is an open source semantic grid framework built on top of Sass and Bourbon…</article>
</section>
// Enter Neat
section {
#include outer-container;
aside { #include span-columns(3); }
article { #include span-columns(9); }
}
// And the result is...
As they say: "it relies entirely on Sass mixins and does not pollute your HTML" which seems the way you're looking for.
I recommend you have a look at sass placeholder classes http://sass-lang.com/documentation/file.SASS_REFERENCE.html#placeholders in order not to bloath your css. Most likely you won't be using every single element included in bootstrap and placeholders only get written to your stylesheet if they are actually extended in your code.
Also, I think people tend to get confused about how css frameworks work and how decoupling css and html actually works.
For very large websites (or ones that you expect eventually to grow very large), where performance and css file size is crucial, some kind of OOCSS approach is your best bet. And this means inevitably that you have formatting code directly in your HTML.
If you can allow yourself to be a little less efficient and want your HTML clean, make sure to use semantic classes (examples for buttons: call-to-action, call-to-action-secondary, submit, btn-primary, btn-corporate-color, etc...)
Also remember to decouple your JS from CSS! use special classes for attaching behaviour (example js-submit, js-call-to-action, etc....)
Last but not least: don't plan for updating your css framework. These frameworks are meant to give you a headstart, not to be your overall design solution. Extend them, adapt them, make them your own, invest in design and create your own look in order to make your app unique.
If what makes you think of updating is a worry to keep up with standard changes, better use compass mixins.
Use #extend, but don't quote selectors:
.button {
#extend .btn;
}
Then you'll see that Sass extends related selectors too, like you want (.form-search .input-append .btn etc.).
… besides the bunch of extra selectors that will be added each time we extend a bootstrap class just to use a different name …
#extend works by copying selectors. If you don't want that, you can "extend" in HTML instead -- i.e. add Bootstrap's class names. :)
For being new to most of this, you're on the right track; the resources you've been reading are excellent. But, I think the concerns you have might not be justified:
...the button won't get the right style because sass will not apply that same rule to our custom class name...
In fact, I think you must be mistaken. According to the Sass documentation:
#extend works by inserting the extending selector (e.g. .seriousError) anywhere in the stylesheet that the extended selector (.e.g .error) appears.
See http://sass-lang.com/documentation/file.SASS_REFERENCE.html#how_it_works for the full code example.
Your original solution was actually correct. Use extends, but without the quotes:
.button {
#extend .btn; //no quotes
}
I tested this using your example, and it works correctly. Sass copies all the selectors with ".btn" and on those newly created selectors, it replaces ".btn" with ".button".
Also, if Sass produces too much duplication for your liking, don't worry about it (so long as you are following best practices as pointed out by the links you posted). Duplicate code is easily compressed if the server uses gzip or the equivalent; the client shouldn't notice any slower loading times, although it might take slightly longer to "unzip" the CSS. As for CSS selector speed, don't worry about that either; the only case where speed matters for selectors is on the JavaScript side, particularly with jQuery. For your Sass code, simply follow best practices for maintainability (notably, modularization as you are trying to do, i.e. SMACSS) and you'll be good to go.
The answers given by sam and tjklemz will help you resolve your immediate technical challenge, but it's possible to decouple your CSS and HTML even more. I'll give an example below, but keep in mind that this is just a quick example to demonstrate the power of mixins/extending CSS classes.
I'd also strongly recommend checking out the ZURB Foundation framework, as it is natively SASS, and designed with this style of development in mind.
For example:
<body>
<div id="my-header">
<h1>My Company</h1>
<h2>My Tagline</h2>
</div>
<div id="my-main">
<div class="my-widget">
<h1>Widget Title</h1>
<a>Widget Option 1</a>
<a>Widget Option 2</a>
</div>
</div>
</body>
With the accompanying SCSS:
//these examples wouldn't really work
//because bootstrap needs more markup
#my-header {
#extend .navbar;
}
#my-header h1 {
#extend .branding;
}
#my-main {
#extend .container;
}
//good example
.my-widget {
#extend .well;
#extend .hero-unit;
}
.my-widget a {
#extend .btn;
}

using Bootstrap and foundation together?

I am using twitter bootstrap for layout and css. But I like the foundation top bar navigation over what bootstrap provides. I tried to use the top bar code inside my html (built with bootstrap) and it messes up the layout. That is not surprising because both of them rely extensively on class named "row" and they have different properties.
One of the options I could think off is to override the row class some how in my style sheet but that would be too much of a work and doesn't seem right.
Other option might be using iframe.
Is there any other way this issue can be solved?
Ideally, you only need to use the top-bar CSS and JS code of Foundation, since that is the only component you mean to use. Here is the SCSS file (with dependancies on the variables declared in _settings.scss. Or you can use the generated CSS code.
If you still need to use .row, just copy the .row styling and name it different. I.e:
/* The Grid ---------------------- */
.foundation-row { width: 1000px; max-width: 100%; min-width: 768px; margin: 0 auto; }
Finally, dont't forget to include the jquery.foundation.topbar.js file and calling
$(document).foundationTopBar();
Old question but thought I'll share the latest if someone is looking for a seamless solution: Web Components
It's a bit of a more complex subject but will allow you to create widgets within completely isolated Shadow DOM's without overriding a thing. Read more about it
here and here. Then you'll be able to do something like this:
<template id="templateContent">
<style> #import "css/generalStyle.css"; </style>
</template>
Taken from this answer
Using an iframe for this is a bad idea. If you like the style for the Foundation top bar, just copy those styles into a custom class in your stylesheet.
Please note that you may have to override some of Bootstrap's default styles for the top bar to get it right.

Resources