CSS positioning to fill container: width vs. left/right? - css

Considering:
For elements that are absolutely positioned inside a relatively
positioned container.
If you want the element to fill the width of the container.
The element is also bottom-aligned.
Is it best for maximum browser compatibility to set a width in pixels for the element, or simply use left and right?
Any common bugs to watch out for with either method?
Clearly, using left: 0; and right: 0; would make the code more manageable in cases where the image's width or padding were to change, but are there any downsides where width: 300px would be favorable instead?

Historically we learnt to use width instead of left & right because IE6 didn't support
at the same time the two properties of the same axis
<div style="top:0;bottom:0;position:absolute;">modern browsers</div>
<div style="top:0;height:100%;position:absolute;">MSIE6</div>
<div style="left:0;right:0;position:absolute;">modern browsers</div>
<div style="left:0;width:100%;position:absolute;">MSIE6</div>
<div style="left:0;right:0;top:0;bottom:0;position:absolute;">modern browsers</div>
<div style="left:0;top:0;height:100%;width:100%;position:absolute;">MSIE6</div>
Also, this technique will not work on some elements (including on modern browsers, by spec )
<!-- these will not work -->
<!-- edit: on some browsers they may work,
but it's not standard, so don't rely on this -->
<iframe src="" style="position:absolute;top:0;bottom:0;left:0;right:0;"></iframe>
<textarea style="position:absolute;top:0;bottom:0;left:0;right:0;"></textarea>
<input type="text" style="position:absolute;left:0;right:0;">
<button ... ></button>
and possibly others... (some of these can't even be display:block)
But, analysing what happens in the normal static flow using the width:auto property
<div style="width:auto;padding:20px;margin:20px;background:lime;">a</div>
You will see it's very similar to...
<div style="width:auto;padding:20px;margin:20px;background:lime;
position:absolute;top:0;left:0;bottom:0;right:0;">b</div>
... same properties with the same values! This is really nice! Otherwise it will look like:
<div style="width:100%;height:100%;
position:absolute;top:0;left:0;">
<div style="padding:20px;margin:20px;
background:lime;">c</div>
</div>
Which is also different, because the inner div doesn't fill the y axis.
To fix this we will need css calc() or box-sizing and an unnecessary headache.
My answer is, left + right | top + bottom are really cool since they are closest to the static positioning's width:auto
and there is no reason to not use them. They are way easier to use compared to the alternative and they
provide much more functionality (for example, using margin-left, padding-left and left at the same time in
one single element).
left + right | top + bottom is considerably
better supported by browsers compared to the alternative width:100% + box-sizing | calc()
and it's also easier to use!
Of course if you don't need (as in your example) to grow the element also in the y axis,
width:100% using some nested element for the padding, it's the only solution to archive support also for MSIE6
So, depends by your needs. If you want to support MSIE6 (it's the only actual reason to do that) you should use with:100%, otherwise use left + right!
Hoping to be helpful.

Both methods are fine, but if you want your design to be responsive or mobile phone compatible - I would recommend using Left: and Bottom: if the container is not enclosed in <div>.
If it is enclosed in a <div> then doing it with width: 100% ormax-width: 200px is a way in my opinion that causes least display problems.
Avoid using fixed widths in CSS if you want your theme to be responsive.

Both of the solution is working in every browser without any problems. In these cases I like to add a width: 100%; left: 0; bottom: 0; for the element, but if you like left:0;right:0; bottom:0; more, than you can use that, too.

I haven't tested this on all browsers (and modes) but for the IE quirks mode (e.g. in an .HTA without !DOCTYPE defined), I have created a subroutine that corrects the WIDTH or HEIGHT on elements where the LEFT/RIGHT style or the TOP/BOTTOM style are set (not “auto”). To avoid going in to all kind of unit conversions, the routine temporary removes the LEFT (or TOP) style and sets the WIDTH (or HEIGHT) to 100% to determine the RIGHT (or BOTTOM) offset in pixels.
The script is written in VBScript, but it should be do difficult to translate the idea to JavaScript.
<html>
<head>
<script language="VBScript">
Option Explicit
Sub Justify(ByVal hElement)
Dim sStyleTop, iTop, iBottom, sStyleLeft, iLeft, iRight
With hElement
If .currentStyle.top <> "auto" And .currentStyle.height = "auto" And .currentStyle.bottom <> "auto" Then
iTop = .offsetTop
sStyleTop = .currentStyle.top
.style.top = "auto"
.style.height = "100%"
iBottom = -.offsetTop
.style.height = .offsetHeight - iTop - iBottom & "px"
.style.top = sStyleTop
End If
If .currentStyle.left <> "auto" And .currentStyle.width = "auto" And .currentStyle.right <> "auto" Then
iLeft = .offsetLeft
sStyleLeft = .currentStyle.left
.style.left = "auto"
.style.width = "100%"
iRight = -.offsetLeft
.style.width = .offsetWidth - iLeft - iRight & "px"
.style.left = sStyleLeft
End If
For Each hElement In .Children
Justify hElement
Next
End With
End Sub
Sub window_onload
Justify Document.body
End Sub
</script>
<style type="text/css">
body {
position:absolute;
width:100%;
height:100%;
}
#outer{
background:blue;
position:absolute;
top:10px;
right:20px;
bottom:30px;
left:40px;
}
#inner{
background:green;
position:absolute;
top:40px;
right:30px;
bottom:20px;
left:10px;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner">
</div>
</div>
</body>
</html>
The command to justify all elements in a document is:
Justify Document.body
I am invoking this from the onload event as it concerns a fixed size .HTA in my case but I expect the routine also to work on the onsize event for sizable windows (or parent elements).

Related

Sign In With Google button responsive design

Is there any way to make the new "Sign In With Google" button responsive? Specifically, vary the width based on the width of the containing element? I'd really just like to set the width to 100%.
I'm aware I can set the data-width attribute but this sets it to an explicit width and doesn't update if you change it after the initial script load - you have to reload the whole script to resize the width.
This isn't a perfect solution but it works for us. We're using Twitter Bootstrap.
The new JavaScript library has a renderButton method. You can therefore render the button multiple times on one page passing different widths to each button using something like this (400 is the max width allowed by the library)
private renderAllGoogleSignInButtons(): void {
this.renderGoogleSignInButton(document.getElementById('google-signin-xs'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-sm'), 280);
this.renderGoogleSignInButton(document.getElementById('google-signin-md'), 372);
this.renderGoogleSignInButton(document.getElementById('google-signin-lg'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-xl'), 400);
}
private renderGoogleSignInButton(element: HTMLElement, width: number){
const options {
type: 'standard',
....
width: width
};
google.accounts.id.renderButton(element, options);
}
We then use the display classes from bootstrap to hide/show each button depending on the size.
<div class="mx-auto" style="max-width: 400px">
<div class="d-none-sm d-none-md d-none-lg d-none-xl">
<div id="google-signin-xs"></div>
</div>
<div class="d-none d-none-md d-none-lg d-none-xl">
<div id="google-signin-sm"></div>
</div>
<div class="d-none d-none-sm d-none-lg d-none-xl">
<div id="google-signin-md"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-xl">
<div id="google-signin-lg"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-lg">
<div id="google-signin-xl"></div>
</div>
</div>
We use a wrapper container with mx-auto and a max-width to center the buttons but you don't have to do this.
Our actual implementation is slightly different than the above as we're using Angular and the button is a component but you can get the idea from the above.
The only drawback with this method is that the "personalized button" doesn't seem to display for all rendered buttons but it doesn't seem to affect their functionality.
This answer is based on the new Google Identity Services.
You could try listening for a resize in the window using the resize event, then re-render the Google Sign In button on change. The assumption here is that the container will respond to match the window size:
addEventListener('resize', (event) => {});
onresize = (event) => {
const element = document.getElementById('someContainer');
if (element) {
renderGoogleButton(document.getElementById('googleButton'), element.offsetWidth); // adjust to whatever proportion of the "container" you like
}
}
renderGoogleButton(element, width) {
const options = {
type: 'outline',
width: width
}
google.accounts.id.renderButton(element, options);
}
I've also had better results when the button is centered, not left aligned. The following in Bootstrap:
<div class="d-flex justify-content-center">
<div id="googleButton"></div>
</div>
NB: The max width for the Google button as of the time of writing is 400px, so bear that value in mind as the limit.
I did a workaround, and it worked for me. As I needed the button to have 100% width in mobile devices.
If you have another element on the screen that behaves the same way you need (like having its width 100%), you can select it using a querySelector, and get its width element.clientWidth, after this you can pass the width to the renderButton function provided by google.
But this solution is not valid if you would like the button to change its size on resizing.
I used transform: scale like this in the CSS:
.sign_in_btn_wrapper {
transform: scale(1.5, 1.5);
float: left;
margin-left: 20vmin;
font-weight: bold;
}
Then, instead of wrapping it as I intended, I found that it was fine to just add the class directly to the goog div:
<div class="g_id_signin sign_in_btn_wrapper"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left"
data-width="250">
</div>
By fiddling with combinations of data-size and data-width, along with the scaling factors, I was able to make it the size I wanted. You can use CSS media queries to adjust the 'transform: scale' values so that it is 'Responsive' to the display size of the user's device. You could also use other trickier methods by having JS tweak variables in your CSS that are then used to set the scaling factors.
Good luck. You'd think it'd be in the interest of these big 'sign in with' providers to get together a coordinating working group to make it easier for web site developers to make all the sign-in buttons the same damn size -- you know they'd rather not have their button come out smaller, and pages look better when things are uniform. And what's with only having dimensions in pixels? At least give us vw, vh, and my favorite: vmin. (Using vmin to set things like font size means you can often skip more tedious RWD contortions and call it good enough.) </end_rant>

ngx-gallery width and height options missing

I'm wondering, how to give ngx-gallery (https://github.com/MurhafSousli/ngx-gallery) a new height. It has a fixed value of 500px and changing the parent divs height is not changing anything.
I was looking either for some attribute in the template like this
<gallery
[height] = '250px'>
</gallery>
Stackblitz: https://stackblitz.com/edit/angular-osh1vu
Followup-question: In the Stackblitz, the behaviour is fit-height (regarding the black background) and in my application it is fit-width, so the black stripes are above and under the image. How can i change this too?
(which was possible on older? version , but is no more a valid attribute)
or
some css code (looking in the dev tools, the sliding images are labeled div.g-template.g-item-template), which is also not possible to overwrite:
div.g-template.g-item-template {
height: 200px !important;
}
Demo add class to galery element
<div class="basic-container">
<h2>Gallery component</h2>
<gallery class="custom"
[items]="items"
[dots]=true
[thumb]=false
[loop]=false
[playerInterval] = 5000
[autoPlay]=true
[loadingStrategy]=preload>
</gallery>
</div>
in css change
.custom{
height:200px;
}

Css print : page margin conflicts with fixed title

I am looking for a way to set a print-devoted css that shows a fixed title on every page.
Unfortunately, I couldn't manage to print this title nicely on the 2nd page, since it always "walks on " the table, ignoring declared body padding / margin ... though I am quite sure the body is not suited here, I couldn't find any working way.
Any idea?
<h2 id="tableTitle">Fixed title</h2>
<button class="noPrint" onclick="myFunction()">Print this table</button>
<table>...content fitting at least 2 pages ...</table>
...
body{
margin-top:100px;
}
#tableTitle {
position: fixed;
top : 0;
}
Here's the fiddle

Looking for a more robust way to automatically resize contents to viewport

I'm trying to keep an svg:rect sized to fit exactly in the visible viewport (with a 20px margin), irrespective of resizing of said viewport. I'm doing this with JS (and friends)1, but I find that this approach is not very robust (nor particularly responsive, for that matter). (E.g. there are hard-to-reproduce situations in which the size of one of the margins is twice as big as it should be, or when a vertical scrollbar pops up for no obvious reason.)
BUT the purpose of this post is not to find better JS for solving this problem, since I am convinced that this problem is really not a job for JS; it should be dealt with via a suitable CSS spec. (The only reason I resorted to JS for it is that all my efforts at doing it with CSS failed, but then again, I know that I am severely CSS-challenged.)
So my question is: What's the proper CSS for this?
1 For completeness, this jsFiddle shows (though not very accurately, unfortunately) what I'm doing now, but the essence of it is in this JS snippet:
(function ($) {
var margin = 20,
viewport = document.documentElement,
canvas = d3.select('#canvas'),
voodoo = 5, // wards off evil v-scrollbar spirits
hmargin = 2 * margin,
vmargin = 2 * margin + voodoo;
$('body').css('margin', margin);
resize_canvas();
$(window).on('resize orientationChanged', resize_canvas);
function resize_canvas () {
canvas.attr({width: viewport.clientWidth - hmargin,
height: viewport.clientHeight - vmargin});
}
})(jQuery);
I think you can achieve what you want through pure css
If you add a container around your svg and add the following attributes to your rect:
<div id="margin-container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect id="canvas" width="100%" height="100%" style="fill:rgb(255,255,255);"></rect>
</svg>
</div>
You can use the following css:
html {height:100%;}
body,
html {padding:0; margin:0; background:black; position:relative; width:100%; min-height:100%;}
#margin-container {position:absolute; top:20px; right:20px; left:20px; bottom:20px;}
svg {width:100%; height:100%;}
Example

body background-image change with fade effect mootools

I'm changing my background-image css property using Mootools:
$(document.body).setStyle('background-image','url(' + pBackground + ')');
And it's its working, but how can a make one fade effect between picture change?
Thanks,
Pedro
You can't fade a background specifically... you have to fade the element that has the background.
For your situation, I would suggest using a <div> that encompasses everything in the <body> of your HTML, ie:
<html>
<body>
<div id="main">
</div>
</body>
You could then set the background-image property of the #main div, and do something like this:
function backgroundChange(pBackground)
{
var m = $('main');
var fx = new Fx.Tween(m,{
duration: 1500,
onComplete: function(){
m.setStyle('background-image','url(' + pBackground + ')');
m.fade('in');
}
});
fx.start('opacity',1,0);
}
Just as a caution, any child elements of that div will also fade, so if you want the background to fade while elements over it remain opaque, you will need to absolutely position any child elements.
Absolutely positioning all elements brings other problems with it when you have variable length content, but there are ways around that too.
Not sure of what i am saying, BUT since it's not a part of the html document, it's not an 'element' so javascript should not be able to work on it.
But, just an idea, and depending on how your site looks, you could try to set an opacity, to simulate an opacity on the body, which can lead to the effect you want..

Resources