Workaround for CSS vw bug with desktop scaling in IE9 - css

I'm using the CSS vw property in a page to give a <div> 50% page width (this is just an example). Here is the code:
*
{
/* Zero padding/margin by default. */
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
}
#left
{
left: 0;
width: 50vw; /* SHOULD BE 50% WIDTH! */
margin: auto;
padding: 0;
top: 50px;
bottom: 50px;
position: absolute;
background: #f00;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body>
<center>|</center>
<div id="left"></div>
</body>
</html>
There is a red box that should take up the left half of the page (halfway indicated by the |). It works fine normally, but when you set desktop scaling on Windows to 125% (default is 100%) it doesn't work in IE9. With desktop scaling at 125% it looks correct in Firefox:
And incorrect in IE9:
My question is: does anyone know of a workaround for this?
This is the setting that causes the problem (Windows 7):

See edit below.
I came up with a vaguely clean solution. Fortunately Windows only supports a few values of desktop scaling: 100%, 125%, 150% in Windows 7, and 200% in Windows 8 (or 8.1? I don't remember). And even more fortunately, it reports the correct relative-to-96 DPI via CSS media queries. All in all it means you can do this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<style>
*
{
/* Zero padding/margin by default. */
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
}
#left
{
left: 0;
width: 50vw;
margin: auto;
padding: 0;
top: 50px;
bottom: 50px;
position: absolute;
background: #f00;
}
</style>
<!--[if IE]>
<style>
/* Windows 125% scale. */
#media (resolution: 120dpi) {
#left {
width: 40vw; /* 50 / 1.25 */
}
}
/* Windows 150% scale. */
#media (resolution: 144dpi) {
#left {
width: 33.333vw; /* 50 / 1.5 */
}
}
/* Windows 200% scale. */
#media (resolution: 192dpi) {
#left {
width: 25vw; /* 50 / 2 */
}
}
</style>
<![endif]-->
</head>
<body>
<center>|</center>
<div id="left"></div>
</body>
</html>
Quite hacky, but not too bad, and it works perfectly. It does mean you have to calculate multiples of all your vw and vh values though.
Edit
As noted in the comments, it works fine unless you zoom with the mouse wheel as well as have desktop scaling on. Frankly, IE9 is fucked. I ended up going with this javascript which doesn't work perfectly still:
<script>
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
for (var i = 0; i < document.styleSheets.length; ++i) {
var factor = screen.systemXDPI / screen.logicalXDPI;
var rules = document.styleSheets[i].cssRules;
for (var j = 0; j < rules.length; ++j) {
var style = rules[j].style;
for (var k = 0; k < style.length; ++k) {
// This is weird I know.
// Change style names from 'max-height' to 'maxHeight'.
styleName = style[k].replace(/\-(\w)/g, function(str, letter) {
return letter.toUpperCase();
});
if (style[styleName] != undefined) {
// Replace vw and vh's.
newVal = style[styleName].replace(/([.0-9]+)(v[wh])/g, function(str, num, unit) {
return (parseFloat(num) / factor) + unit;
});
if (style[styleName] != newVal) {
style[styleName] = newVal;
}
}
}
}
}
</script>

Related

css variables defined under :root could not be found?

:root{
--errorColor: #ff665d;
}
::-webkit-scrollbar-thumb {
/* --errorColor is not defined */
background-color: rgba(var(--errorColor), 0.8);
}
demo: https://codepen.io/ZeronoFreya/pen/VwBQarJ
What should I do?
Thank you for your help, I am a little confused about the syntax of scss and css
Don't believe everything you read!
--errorColor is defined, but it seems that the changing of background in that pseudo element does not work unless the scrollbar is set to auto (I haven't yet found a definitive reference for this). You could test this out without use of a CSS variable, e.g. try setting with background-color: red.
However, you have another problem which is that the format for the background-color isn't going to work with that hex code color (see answer from #BernardBorg) so use an rgb setting instead.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
:root {
--errorColor: #ff665d;
--errorColor: 255, 102, 93;
}
div {
width: 300px;
height: 300px;
border: 1px red solid;
overflow: auto;
}
::-webkit-scrollbar-thumb {
background-color: rgba(var(--errorColor), 0.8);
}
::-webkit-scrollbar {
overflow: auto;
}
</style>
</head>
<body>
<div id="div"></div>
<script>
let div = document.querySelector("#div")
let str = ""
for (let i = 0; i < 100; i++) {
str += `<p>${i}</p>`
}
div.innerHTML = str
</script>
</body>
</html>
rgba(hexcode, 0.8) is invalid CSS. You could do the following instead;
:root{
--errorColor: 255, 102, 93;
}
::-webkit-scrollbar-thumb {
background-color: rgba(var(--errorColor), 0.8);
}
Source
I spent a while trying to figure out why the background-color wasn't getting applied to the scrollbar thumb, but it seems someone else has figured it out before me. Please refer to #AHaworth's answer and #TemaniAfif's comment on his answer
(setting appearance: none or overflow: auto on ::webkit-scrollbar)
Extra note: if you want the colour to only apply to the div's scrollbar you can do
#div::-webkit-scrollbar {
appearance: none;
}
#div::-webkit-scrollbar-thumb {
background-color: rgba(var(-errorColor), 0.8);
}

simple css stylish printing woes

I am trying to "engineer" a cover page in html+css that shows appropriately in browsers, fits exactly on the (A4) page, and prints it with background colors. no javascript---it has to go to epub2. I am enclosing my first attempt at a prototype. (the actual cover page will of course be more complex.)
the bad news is that it's already not working. the worse news is that it's not working differently in firefox and chromium under linux---and I have not even tried safari, IE, OSX, iOS, Android, and Windows yet.
I am not averse to starting over, as long as I can remain in the html+css paradigm (i.e., I don't want to have to create a png bit image in TeX if it can be avoided.).
can this be done? or is it time to go back to TeX? advice appreciated.
regards,
/iaw
<?xml version='1.0' encoding='utf-8'?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<style type="text/css">
body {
color: #EEFFEE;
font-weight: bold;
page-break-inside: avoid;
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.page {
width: 21cm;
min-height: 29.7cm;
background-color: yellow !important;
color:black;
}
#page {
size: A4;
margin: 0;
}
#media print {
.page {
margin: 0;
page-break-after: always;
}
}
<!-- breaks color: -webkit-print-color-adjust: exact; -->
div.mytitle {
color:red;
background-color: blue;
text-align:center;
}
</style>
</head>
<body>
<div class="page">
<div class="mytitle">
<div style="margin:auto;font-size:100px;">Title</div>
subtitle
</div>
text
</div>
</body>
</html>
So in tinkering with your code if you move the -webkit-print-color-adjust: exact; to end of style it works for me in chrome ie and firefox. You can throw the code in http://www.onlinehtmleditor.net/ will see that it works as long as the line sits underneath your other rules. Hope it helps.
Will

#media print and IE8

My goal is to have this page printed from IE8 without the browser's footer and header appearing on it (page number and url). It prints the page in the landscape position (after inserting a lot of text where is "hello"), so it isn't a #media problem as I was thinking before, but for some reason IE puts his header right over the page text!
It works fine on Chrome, though. Any ideas? Here is my code:
<head>
<!--[if lt IE 9]>
<script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<link rel="stylesheet" media="print" href="/print.css" type="text/css" />
<![endif]-->
<style type="text/css">
#page
{
size: A4;
margin: 0mm;
}
body
{
margin: 0px auto;
}
#media screen, projection{ }
</style>
</head>
<body>
Hello
</body>
And from my print.css:
#media print{
body
{
margin: 0px;
padding: 0px;
}
#page
{
margin: 0in !important;
size: auto landscape;
}
}
By the way, I know I can remove IE's header and footer on Page Setup but the client won't have the project that way.
This documentation may help: http://msdn.microsoft.com/en-us/library/ms530841(v=vs.85).aspx.
Perhaps try:
#page {
#top-left { display: none; }
#bottom-center { display: none; }
/* and so on */
}

IE9/8/7 css sprite position slip issue

I want to css sprite (sprite image total width:45px and total height:15px consists of three image ) but there is a problem in IE9/8/7. link and hover work but when click the button (active) sprite image slipping to left 1px. issue for only IE 9/8/7.How can I fix this?
CSS:
body{
margin:0;
padding:0;
}
.button{
background:url(sprite-image.png) no-repeat 0 0;
width:15px;
height:15px;
cursor:pointer;
}
.button:hover{
background:url(sprite-image.png) no-repeat -15px 0;
}
.button:active{
background:url(sprite-image.png) no-repeat -30px 0;
}
.cont{
width:200px;
height:200px;
float:left;
margin:50px 0 0 100px;
}
HTML:
<body>
<div class="cont">
<div class="button"> </div>
</div>
</body>
"link" and "hover" and "active" FF,Chrome,Safari,Opera like this;
but IE 9/8/7 active look like this;
I concretized above images to make it look better . My sprite image;
Why not use IE-conditional comments;
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!-- Consider adding a manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
And then write eg CSS-rules like .lt-ie9 .someclass{}to target a IE-version. I use them to fix some IE-specific css-stuff. No dirty hacks, no hastle just css. Did you check with eg Firebug Lite what happens?! outline: 0 none?
Add a Internet explorer specific stylesheet to the <head></head> section.
<!--[if lt IE 9]>
<link rel="stylesheet type="text/css" href="/css/ie.css" />
<![endif]-->
and in ie.css do something like:
.button:active{
background:url(sprite-image.png) no-repeat -29px 0 !important;
}
(There's Always an issue with ie , phew !)
I created a fake sprite using your graphic to see what you are seeing but looking good in my fiddle in all IE 7-9 (note i just change positioning and made it construsive (less):
http://jsfiddle.net/Riskbreaker/Rr8p2/
body{
margin:0;
padding:0;
}
.button{
background:url(images/sprite.png) no-repeat 0 0;
width:14px;
height:15px;
cursor:pointer;
}
.button:hover{
background-position:0px -27px;
}
.button:active{
background-position:0px -27px;
}
.cont{
width:200px;
height:200px;
float:left;
margin:50px 0 0 100px;
}
Remember the positioning I made up so you can adjust. I never had the active IE issue before...but let me know what you are seeing....if the issue persist and you don't want another file then do this:
IE7: *.button:active{background-position:0px -28px;} (or whatever the correct position is )...
IE8: .button:active{background-position:0px -28px\9;}.........
IE9....not sure your latest but it should not have any issues (latest)
I have faced similar issues with IE8 before but IE9 worked fine in my case (not sure about IE7 but it must be like IE8 for this thing).
It can be resolved/improved by one of these 2 approaches:
1) Modify the image (maybe in resolution, color combination etc.) and try if it works. Why this might work? Because in your example, IE appears trying to do some image manipulations "intelligently" which unfortunately go wrong at times (especially for small images/pixel perfect cases) and you can just hope that it doesn't fail badly for your new images.
2) Use background-position accuracy of 0.5px units.
Note "background-position: -15.5px 0;" in the following code. This solution will reduce your frustration by at least 50% :-) I am afraid that you might need to provide IE specific CSS for this solution but that should be fine ... You can add the browser identifier class name on tag using JavaScript or with technique mentioned # http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ and then use those class names when you write browser specific CSS.
The solution:
.button {
background:url(images/sprite.png) no-repeat 0 0;
width: 15px;
height: 15px;
cursor:pointer;
}
.button:hover {
background-position: -15.5px 0;
}
.button:active {
background-position: -30px 0;
}
.cont {
width: 200px;
height: 200px;
float: left;
margin: 50px 0 0 100px;
}
You can use below trick which will help to give manual value
For IE7 (underscore before the value)
.button:hover {
background-position: _-15.5px 0;
}
Or
IE-7 & IE-8(need to add\9)
.button:hover {
background-position: -15.5px\9;
}
For IE8only (\0/)
*+.button:hover {
background-position: -15.5px\0/;
}
Try this change in css:
.button{
background: url(sprite-image.png) no-repeat left 0;
width: 15px;
height: 15px;
cursor: pointer;
}
.button:hover{
background: url(sprite-image.png) no-repeat center 0;
}
.button:active{
background: url(sprite-image.png) no-repeat right 0;
}

IE 6 vs. position:fixed

position:fixed that doesn't work for Internet explorer 6. I can't really understand the fixes found on google. I need it to work in IE6, IE7, IE8 & FireFox 3.0.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
<title>Sidebar fixed</title>
<style type="text/css">
#wrapper {
position:relative;
width:900px;
margin:0 auto 0 auto;
}
#sidebar_left {
position:fixed;
height:200px;
width:200px;
border:1px solid #000;
}
#sidebar_right {
position:fixed;
height:200px;
width:200px;
margin-left:700px;
border:1px solid #000;
}
#content {
position:absolute;
height:2000px;
width:480px;
margin-left:210px;
border:1px solid #000;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="sidebar_left">
<p>Left sidebar</p>
</div>
<div id="sidebar_right">
<p>Right sidebar</p>
</div>
<div id="content">
<p>This is the content</p>
</div>
</div>
</body>
</html>
Don't support IE6! The sooner people stop hacking sites about for IE6, the less traction it will have and the quicker it will die! Or, add this code after your first style block;
<!--[if IE 6]>
<style type="text/css">
#sidebar_right, #sidebar_left {
position:absolute; /* position fixed for IE6 */
top:expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px');
left:expression(0+((e=document.documentElement.scrollLeft)?e:document.body.scrollLeft)+'px');
}
</style>
<![endif]-->
The result isn't super-smooth, but it does work.
UPDATE
I wasn't too clear on how this should be used; simply add the id (or class) of any elements that have "position:fixed" to the declaration list at the start of the above block and they will behave themselves in IE6.
yes IE6 sucks. here's the hack...
_position: absolute;
_top: expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px');
that basically tells IE6 to keep it absolutely positioned in the top left even as it scrolls.
this should go under the rest of your css for the element so it over-rides it in IE6.
here it is for your left bar...
#leftBar {
position:fixed;
top:0;
left:0;
width:200px;
_position:absolute;
_top:expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px');
}
I just tested this on IETester's version of IE6 and it worked great and... No Jitter, Whoo!
Let say you have a element with a class of box for example...
.box {
position: fixed;
top: 0px;
left: 0px;
}
Replace the opening <HTML> tag with conditional IE statements...
<!--[if IE 6]> <html id="ie6"> <![endif]-->
and
<!--[if !IE]--> <html> <!--[endif]-->
Then like MatW & mitchbryson suggested use 'expression' to simulate position fixed.
Note: This code goes after the original element's styles in the CSS.
#ie6 .box {
position: absolute;
top: expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px');
left: expression(0+((e=document.documentElement.scrollLeft)?e:document.body.scrollLeft)+'px');
}
The problem is that on any page scroll the element will jitter, this is one way to compensate...
Note: This code goes at the top off your CSS or after your styled 'HTML { }' in your CSS.
#ie6 {
background-image:url(about:blank);
background-attachment:fixed;
}
According to Thomas Aylott # SubtleGradient.com ,
"... This forces the processing of the CSS before the page is redrawn. Since it’s processing the css again before redrawing, it’ll go ahead and process your css expressions before redrawing too. This gives you perfectly smooth position fixed elements!""
article link: http://subtlegradient.com/articles/2009/07/29/css_position_fixed_for_ie6.html
For example, all together...
<!--[if IE 6]> <html id="ie6"> <![endif]-->
<!--[if !IE]--> <html> <!--[endif]-->
<HEAD>
<STYLE>
#ie6 {
background-image:url(about:blank);
background-attachment:fixed;
}
.box {
position: fixed;
top: 0px;
left: 0px;
}
#ie6 .box {
position: absolute;
top: expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px');
left: expression(0+((e=document.documentElement.scrollLeft)?e:document.body.scrollLeft)+'px');
}
</STYLE>
</HEAD>
<BODY>
<div class="box"></div>
</BODY>
</HTML>
Found this solution which I tweaked ( Basically the lines I changed was: $('#sidebar_left').css('top',document.documentElement.scrollTop); ):
// Editing Instructions
// 1. Change '#your_div_id' to whatever the ID attribute of your DIV is
// 2. Change '175' to whatever the height of your header is, if you have no header, set to 0
/********************************
* (C) 2009 - Thiago Barbedo *
* - tbarbedo#gmail.com *
*********************************/
window.onscroll = function()
{
if( window.XMLHttpRequest ) {
if (document.documentElement.scrollTop > 299 || self.pageYOffset > 299 && document.documentElement.scrollBottom > 100) {
$('#sidebar_left').css('top',document.documentElement.scrollTop);
$('#sidebar_right').css('top',document.documentElement.scrollTop);
} else if (document.documentElement.scrollTop < 299 || self.pageYOffset < 299) {
$('#sidebar_left').css('top','299px');
$('#sidebar_right').css('top','299px');
}
}
}
It jitters and looks bad, but work on all browsers including IE6.
I recently wrote a jQuery plugin to get position:fixed working in IE 6+. It doesn't jitter on scroll, it looks at capability (not user-agent), works in Internet Explorer 6, 7, 8.
If you use strict mode in IE7+ position:fixed will be honoured, but by default IE7+ operates in Quirks Mode. This plugin checks for browser capability, and if it doesn't honour position:fixed, then it implements the jQuery fix.
http://code.google.com/p/fixedposition/
Something like this may work for you:
$(document).ready(function(){
$("#chatForm").fixedPosition({
debug: true,
fixedTo: "bottom"
});
});
You may need to make some minor CSS adjustments to get it working for your code. I'm working on "offset" values as options as we speak.
It is possible to do it with CSS expression, but with some extra hack to get a smooth scrolling:
html, body {
_height: 100%;
_overflow: hidden
}
body {
_overflow-y: auto
}
#fixedElement {
position: fixed;
_position: absolute; / ie6 /
top: 0;
right: 0
}

Resources