I've been playing a little bit with CSS3 flexible box model as described in this article: CSS 3 Flexible Box Model
I am trying to create a simple vbox with a nested hbox, something like this:
<div class="vbox">
<div>Header</div>
<div class="hbox">
<div>Section 1</div>
<div>Section 2</div>
<div>Section 3</div>
</div>
<div>Footer</div>
</div>
However the content of the hbox is being laid out vertically and not horizontally. What am I doing wrong and how to do it correctly? Thanks.
The problem is that the display: box; declaration in the .hbox rule gets overridden by the display: block; in the .vbox > * rule. You have two options:
1 Make the display: box override the more specific rules:
.hbox {
display: -webkit-box !important;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box !important;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box !important;
box-orient: horizontal;
box-align: stretch;
}
Approach 1 working example here, the main disadvantage of this approach is that you're messing with the default specificity rules of CSS which may cause confusion in other places.
2 Remove display: block from the more specific rules:
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
Approach 2 working example here, the main disadvantage of this approach is that you'll need all direct children of an .hbox or .vbox to be block level elements.
Related
I wrote a Google Chrome extension, which popups a dialog with an autocomplete field and it's own style, but there are some sites where my CSS gets totally broken, which doesn't look very nice.
I know about isolating styles with iFrames, but in Google Chrome extension there is no way to isolate my HTML and CSS in this way. Another method is to wrap all my stuff into a separated div with it's own id and relative styles for that id, and I do so, but it seems that it doesn't work on some sites with "hard" tags style overloading or "!important" directives in the CSS code.
So, I want to know is there any way to really isolate my styles in z convenient way or it's my bad carma to overload every little CSS property to fix one or another style issue for each site?
By the way: I set up my manifest to load all the things at the "document_end", but I see it's not being applied to the stylesheets which is every time loaded whenever the DOM is ready.
At the time of asking the question, your only option was to either use iframes, or stylesheets with a very high specificity and explicitly set all properties that might affect styles. The last method is very cumbersome, because there will always be some property that is overlooked by you. Consequently, the only usable method for isolating stylesheets was to use iframes.
The solution to this problem -isolation of styles without iframes- is Shadow DOM (since Chrome 25). You can find a tutorial at HTML5 Rocks. For a real-world Chrome extension that uses Shadow DOM to isolate styles, see Display #Anchors (source code here).
As I've recently gone through the gauntlet of this issue, I want to share some information I think is valuable.
First, Rob W's answer is correct. Shadow DOM is the correct solution to this problem. However, in my case not only did I need CSS isolation, I also needed JavaScript events. For example, what happens if the user clicks a button that lives within the isolated HTML? This gets really ugly with just Shadow DOM, but we have another Web Components technology, Custom Elements, to the rescue. Except that as of this writing there is a bug in chrome that prevents custom element in chrome extensions. See my questions here and here and the bug here.
So where does that leave us? I believe the best solution today is IFrames, which is what I went with. The article shahalpk linked is great but it only describes part of the process. Here's how I did it:
First, create an html file and js file for your isolated widget. Everything inside these files will run in an isolated environment in an iframe. Be sure to source your js file from the html file.
//iframe.js
var button = document.querySelector('.my-button');
button.addEventListener('click', function() {
// do useful things
});
//iframe.html
<style>
/* css */
</style>
<button class='my-button'>Hi there</button>
<script src='iframe.js'></script>
Next, inside your content script create an iframe element in javascript. You need to do it in javascript because you have to use chrome.extension.getURL in order to grab your iframe html file:
var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL("iframe.html");
document.body.appendChild(iframe);
And that's it.
One thing to keep in mind: If you need to communicated between the iframe and the rest of the content script, you need to chrome.runtime.sendMessage() to the background page, and then chrome.tabs.sendMessage from the background page back to the tab. They can't communicate directly.
EDIT: I wrote a blog post detailing everything I learned through my process, including a complete example chrome extension and lots of links to different information:
https://apitman.com/3/#chrome-extension-content-script-stylesheet-isolation
In case my blog goes down, here's the sources to the original post:
Blog post
Example source
Either use all
.some-selector {
all: initial;
}
.some-selector * {
all: unset;
}
or use Shadow DOM
Library
function Widget(nodeName, appendTo){
this.outer = document.createElement(nodeName || 'DIV');
this.outer.className = 'extension-widget-' + chrome.runtime.id;
this.inner = this.outer.createShadowRoot();
(appendTo || document.body).appendChild(this.outer);
}
Widget.prototype.show = function(){
this.outer.style.display = 'block';
return this;
};
Widget.prototype.hide = function(){
this.outer.style.display = 'none';
return this;
};
Usage
var myWidget = new Widget();
myWidget.inner.innerHTML = '<h1>myWidget</h1>';
You can access the widget contents via myWidget.inner and the outer via myWidget.outer.
Styles
/*
* Reset Widget Wrapper Element
*/
.extension-widget-__MSG_##extension_id__ {
background: none;
border: none;
bottom: auto;
box-shadow: none;
color: black;
cursor: auto;
display: inline;
float: none;
font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: inherit;
font-style: normal;
font-variant: normal;
font-weight: normal;
height: auto;
left: auto;
letter-spacing: 0;
line-height: 100%;
margin: 0;
max-height: none;
max-width: none;
min-height: 0;
min-width: 0;
opacity: 1;
padding: 0;
position: static;
right: auto;
text-align: left;
text-decoration: none;
text-indent: 0;
text-shadow: none;
text-transform: none;
top: auto;
vertical-align: baseline;
white-space: normal;
width: auto;
z-index: 2147483648;
}
/*
* Add your own styles here
* but always prefix them with:
*
* .extension-widget-__MSG_##extension_id__
*
*/
.extension-widget-__MSG_##extension_id__{
position: fixed;
top: 100px;
margin: 0 auto;
left: 0;
right: 0;
width: 500px;
}
.extension-widget-__MSG_##extension_id__::shadow h1 {
display: block;
margin: 0 auto;
padding: 20px;
background-color: yellow;
border: 10px solid green;
font-size: 20px;
text-align: center;
}
I recently created Boundary, a CSS+JS library to solve problems just like this. Boundary creates elements that are completely separate from the existing webpage's CSS.
Take creating a dialog for example. After installing Boundary, you can do this in your content script
var dialog = Boundary.createBox("yourDialogID", "yourDialogClassName");
Boundary.loadBoxCSS("#yourDialogID", "style-for-elems-in-dialog.css");
Boundary.appendToBox(
"#yourDialogID",
"<button id='submit_button'>submit</button>"
);
Boundary.find("#submit_button").click(function() {
// some js after button is clicked.
});
Elements within #yourDialogID will not be affected by the existing webpage. And find() function returns a regular jQuery DOM element so you can do whatever you want with it.
Hope this helps. Please let me know if you have any question.
https://github.com/liviavinci/Boundary
Use iframes. It's a workaround, but works fine.
Maxime has written an article on it.
It seems like overriding styles does not work consistently. I have this two styled components:
const StreamContentContainer = styled.div`
display: flex;
vertical-align: middle;
flex-direction: column;
flex: 0 100%;
align-items: center;
flex-wrap: wrap;
padding: 1rem;
flex-flow: column wrap;
`;
// new Component based on StreamContentContainer
with additional styles and override stlye
const FullStreamContentContainer = styled(StreamContentContainer)`
height: 56.11vw;
overflow: hidden;
padding: 0;
`;
Know if I use my FullStreamContentContainer there should be no padding. On CSR that works fine, the element shows up in the markup correctly.
But if the element is requested initial with SSR the padding of the StreamContentContainer overrides the FullStreamContentContainer again.
It does not matter if the node is generated on SSR or CSR, it shows up the same way in the markup:
<div class="sc-4y67w2-1 fodYop sc-4y67w2-0 WzHos">...</div>.
But if I inspect the element with the DevTools, I can see that on SSR first the class WzHos shows up and then the class fodYop:
Compared to the rules rendered on CSR the rules occur the other way round - like expected:
Does anybody know what causes this weird behavior and how to avoid it?
Problem resolved: Increased the specificity of FullStreamContentContainer styles by using
const FullStreamContentContainer = styled(StreamContentContainer)`
&&& {
height: 56.11vw;
overflow: hidden;
padding: 0;
}
`;
Relating to the SC docs, the repeated class bumps the specificity high enough to override the source order.
problem image
I applied this class to h3 tag.
.ellipsis-2 {
$lines: 2;
$line-multiple: 1.3;
$font-size: 1em;
display: block;
display: -webkit-box;
max-height: $font-size * $line-multiple * $lines;
line-height: $font-size * $line-multiple;
text-overflow: ellipsis;
overflow: hidden;
word-wrap: break-word;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
}
As you saw in image, there is full lines of text and ellipsis didn't show.
But when I resize screen, ellipsis works fine.
Problem occured only the first time page rendering.
Any adivce?
This is my solution to this:
HTML
<mat-expansion-panel>
<mat-expansion-panel-header>
{{ stuff here }}
</mat-expansion-panel-header>
<div class="mat-expansion-panel-content">
<div class="mat-expansion-panel-body">
{{ stuff here }}
</div>
</div>
</mat-expansion-panel>
CSS
.mat-expansion-panel-body {
visibility: visible;
}
Set visibility property of the panel content's child to visible.
So, you can avoid the wrong rendering on the first load.
I was hitting my head against the wall for two days in order to solve this.
I hope it can save someone some time.
Almost an year old post, still answering as this might help someone.
This could happen if the element with -webkit-line-clamp has it's visibility set to hidden when it first renders, either directly or by inheriting from one of its parent. This is due to this webkit bug: -webkit-line-clamp is not respected when visibility is hidden.
As a workaround, instead of visibility, you can set display: none if possible.
If your problem is with a framework such as Angular that runs a autoprefixer on styles, maybe this solution will work for you:
https://medium.com/#gawadnikita/angular-6-issue-of-line-clamp-css-not-working-a6b591bda9bf
overflow: hidden;`
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
Add a /* autoprefixer: ignore next */ exactly before -webkit-box-orient: vertical; and this should work
Worked for me with Angular in July 2022 on Chrome and Safari, when this block size is constrained by parent with flex-basis:
.your-class {
-webkit-line-clamp: 2;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
word-break: break-word;
}
Thanks to #Leonardo Rick
I'm trying to change places of ofbiz components like application bar and main container places, I know that maybe can be changes from /common/widget/CommonScreens.xml or something like that (such as another xml file), I tired without luck to find what the file responsible to render "app-navigation" and just I lost my way.
So I hope find my answer here, I want to change layout,
The default interface is look like this:
What I want is (I made this using firebug) :
How I can do that?? or in another word from where I can start to do that?
leave the CSS and HTML side for me, I just want the point to start with, to edit theme layout to be like what I explained in previous screenshot.
Sorry If I cant give you what I want clearly my English didn't help me today :) but you can ask me in comment about anything if not clear yet.
take a look at the other themes in OFBiz. The bizness_time theme is already using a similar layout.
Cheers
I solved my issue, there was a little mistake from my side, and I did some modification;
In CSS file:
#app-navigation {
...
/* border-top: 0.1em solid #3E5A71; */ /*Removed*/
...
width: 200px; /*Added*/
float: left; /*Added*/
}
...
#app-navigation ul li ul li {
...
/* float: left;
display: inline; */ /*Removed*/
...
}
/*Added*/
#container:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
In templates :
At appbar.ftl , or appbarOpen.ftl :
<div id="container"> <!-- This is the Line that I Added -->
<#if userLogin?has_content>
...
And in footer.ftl :
</div> <!-- This is the Line that I Added -->
<div id="footer">
...
Simply :)
i'm trying to make up a different look and feel on my sharepoint site. I try to make my main content's width down to 960px under my form tag in sharepoitn designer. when I refresh the page at the first it renders the main content down to 960px but when the page fishished loading the main content stretches itself to the whole screen's width.
I found out that it's because of the onload script running in body tag. but I caanot remove this script because this work has side effects on page functionality.
the function is _spBodyOnLoadWrapper().
does anyone know this function ? or does anyone know how to come up with this problem ?
UPDATE #1:
My css code is as follows.. I added this class to the main Form on master page:
.mainContent
{
width: 960px;
height:100% !important;
min-height:100% !important;
padding-top: 10px;
margin-left: auto;
margin-right: auto;
direction:rtl;
}
UPDATE #2:
I use v4.master template.
I have taken the ribbon out of the form tag. it's directly after body tag. because I wanted the ribbon to be streched at the top. but when i add this line of code
<body onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">
the mainContent blows up. something at the header streches in the whole width and some panels at bottom remains 960px.
you got me interested so I recreated your issue. By default, the javascript will try to inline the width based on its calculations.
However, what you need is to set the class s4-notsetwidth on a wrapping container.
Here is what i did to fix your issue
Add this to the head
<style type="text/css">
#s4-bodyContainer {
width: 960px;
height:100% !important;
min-height:100% !important;
padding-top: 10px;
margin-left: auto;
margin-right: auto;
}
/* Aligns the Top Bars */
.ms-cui-ribbonTopBars {
width: 960px!important;
margin-left:auto;
margin-right:auto;
}
/* Turns off the border on the bottom of the tabs */
.ms-cui-ribbonTopBars > div {
border-bottom:1px solid transparent !important;
}
</style>
Then locate the s4-workspace (that's the immediate parent of #s4-bodyContainer and add class s4-nosetwidth. That should work for you.
Use these two references to achieve exactly what you want (not sure if you want ribbon aligned or not), Randy Drisgill post and Tom Wilson's post.