see fiddle
html
<div class="e" style="left:5px;top:5px;">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb</div>
<div class="e" style="left:5px;top:100px;">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
css
.e {
font-size: 10px;
font-family: arial;
background-color: yellow;
position: absolute;
max-width: 300px;
}
you will notice the 2nd div fits the size of the content exactly, but on the first div there's a bunch of empty space to the right of the a's and b's. This is because the div hit its max width of 300px and then wrapped the b's to a 2nd line. The wrapping is good, but then I would expect the div to then shrink back down to the width of the a's so that there's no empty space to the right.
Is it possible to get it to do this?
Tested in Chrome and FF.
you may avoid handling the width, as my understanding is that you're looking for a way to break the text in a satisfying manner.
use word-break: break-all, to wrap the text whenever it hits the container's edge.
Example:
demo on jsFiddle
Reference:
the CSS3 word-break property on Mozilla Developer Network
To shrink a div (or any element) to the size of its text content, you can use JavaScript to get a range that contains its contents and get the size of the range using range.getBoundingClientRect():
function sizeElementToContents(el) {
var range = document.createRange();
range.selectNodeContents(el);
var textRect = range.getBoundingClientRect();
el.style.width = textRect.width + "px";
}
But, of course, that only works with Modern browsers. IE8 and IE7 have different methods for working with ranges. Actually, IE7 automatically handles max-width the way you want it to, but when our IE8 code is run to re-size the divs on IE7, it shrinks the divs to 0. To avoid writing code for specific browser versions, this code runs on IE7 and IE8, but includes a little extra logic so that it works on both browser versions:
function sizeElementToContents(el) {
var range, width;
if (document.createRange) {
range = document.createRange();
range.selectNodeContents(el);
width = range.getBoundingClientRect().width;
}
else {
range = document.body.createTextRange();
range.moveToElementText(el);
range.moveStart("character", 1);
width = range.boundingWidth;
var height = range.boundingHeight;
range.collapse();
range.moveEnd("character", 1);
if (range.boundingHeight == height) {
return; // text doesn't wrap, so don't resize
}
}
el.style.width = width + "px";
}
Working demo: http://jsfiddle.net/gilly3/HZRFb/
Forking from Biziclop's solution:
.e {
font-size: 10px;
font-family: arial;
background-color: yellow;
position: absolute;
max-width: 300px;
margin-right:100%;
}
Link to the Fiddle.
Don't ask me why it works, it might break tomorrow, but adding some extreme margin-right seems to solve the problem:
.e {
margin-right: 9999px;
}
See http://jsfiddle.net/2cTga/1/
Related
I am having problem with css media query in Firefox. It works correct in Chrome like I made two DIVs and want a scrollbar. If I decrease the screen size of firefox upto 800px then both DIVs collapse and after some pixels media query works but that not happens in Chrome.
check this fiddle http://jsfiddle.net/RMvqC/2/
I SOLVED this issue by calling the "mqGenie" javascript in the head of my project.
Now the widths of my media queries work fine ( with the same value ) on Chrome, Safari, Firefox and IE with or without scroolbars.
This javascript Adjusts CSS media queries in browsers that include the scrollbar width in the viewport width so they fire at the intended size.
You can download it from this url:
http://stowball.github.io/mqGenie/
Firefox & Webkit based browsers render the scrollbar differently. In Firefox, MediaQuery considered width of scrollbar which is 15px with the screen width, but in Webkit based browsers it's not considered scrollbar with the screen width. So, that's why the floated DIVs are collapsed in Firefox.
I did some stuff with css may be that's help you. (check this fiddle)
html {
/* force scrollbars */
height: 101%;
}
body {
margin: 0;
padding:0;
white-space:nowrap;
}
#box1,
#box2 {
display:inline-block;
width: 400px;
height: 200px;
vertical-align:top;
white-space:normal;
}
#box1 {
background: #ce0000;
margin-right:-5px;
}
#box2 {
background: #8e0000;
}
#media screen and (max-width: 799px) {
body {
white-space:normal;
}
#box1,
#box2 {
width: 300px;
}
}
Firefox & Opera follows W3C spec which is to include scrollbar width in media queries width (the reason might be to avoid infinite loop as described in a comment here), while Webkit does not (possibly coz they think it makes no sense)
There is a workaround (I've only tested this on FF), apparently if you force scrollbar to be visible all the time, then the width will now be consistent with Webkit. Here's the code:
html
{
overflow:hidden;
height:100%;
}
body
{
position:relative;
overflow-y:scroll;
height:100%;
-webkit-overflow-scrolling:touch; /* So iOS Safari gets the inertia & rubber-band effect */
}
If you want to apply this to FF & Opera only, you can resort to CSS hacks:
/* Firefox */
#-moz-document url-prefix()
{
html
{
overflow:hidden;
height:100%;
}
body
{
position:relative;
overflow-y:scroll;
height:100%;
/*-webkit-overflow-scrolling:touch;*/
}
}
/* Opera */
x:-o-prefocus, html
{
overflow:hidden;
height:100%;
}
x:-o-prefocus, body
{
position:relative;
overflow-y:scroll;
height:100%;
}
It goes without saying, the caveat is the scrollbar will be visible at all times, which might be an okay compromise.
Play safe!
My final strategy is added 20px to the media queries and that is my default white space on the layout.
With one exception: #media (min-width: 320px) At that size a don't leave the 20px white space and include one more rule to solve minor background issues:
html body {
min-width: 320px;
}
20px is the scroll bar default width size.
FYI: https://www.sitepoint.com/rwd-scrollbars-is-chrome-better/
You can implement a solution for Firefox pretty easily by using a CSS-hack. After wrapping your content in an extra <div> add this lines to your CSS:
/* Firefox-Hack */
body, x:-moz-any-link {
overflow-x: hidden;
}
#wrapper, x:-moz-any-link {
margin: 0 -7.5px;
}
Check the jsbin (jsfiddle is down right now)
To have richer responsive experience you could add another media query: another jsbin
The CSS-hack was found at paulirish.com
This is peripherally related, but I found a way to detect which media-query the browser is actually using at any given moment, without having to muck around with scrollbar and body widths...
Basically, define a an absolutely positioned 1-x-1-pixel-sized list somewhere in your body, with a list-item for each media-query condition you want to be "watchable".
Then in each media-query definition, show/hide the corresponding list-item, and then simply check whether that item is visible from within your script.
Example:
<body>
...
<ul id="mediaQueryHelper">
<li id="desktop"></li>
</ul>
</body>
<style type="text/less">
#mediaQueryHelper {
position: absolute;
height: 1px;
width: 1px;
visibility: hidden;
top: -999px;
left: -999px;
}
#media screen and (min-width: 481px)
{
#desktop { display: inline; }
}
#media screen and (min-width: 320px) and (max-width: 480px)
{
#desktop{ display: none; }
}
</style>
<script type="text/javascript">
$(document).ready(function()
{
var _desktop = $("#desktop");
$(window).resize(function() {
console.log("media-query mode: " + _desktop.is(":visible") ? "DESKTOP" : "MOBILE");
});
});
</script>
Short Answer
If you do not want to display the scrollbar all the time, wrap your content into <div> elements etc. you can use JavaScript to add a certain value to all media queries when the scrollbar is shown.
// check whether scrollbar is visible
var isScrollbarVisible = window.innerWidth > document.documentElement.clientWidth;
// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];
// update media rule
mediaRule.media.mediaText = '..'
Long Answer
I wrote a small script which you can include on your page. It detects when the window is resized and changes all media queries if needed. The value of the css variable --replace-media-scrollbar is used as the width of the scrollbar or 15px if no value was found. This works for the media queries with, min-width, max-width, height, min-height and max-height even when they are connected using and.
JavaScript:
function* visitCssRule(cssRule) {
// visit imported stylesheet
if (cssRule.type == cssRule.IMPORT_RULE)
yield* visitStyleSheet(cssRule.styleSheet);
// yield media rule
if (cssRule.type == cssRule.MEDIA_RULE)
yield cssRule;
}
function* visitStyleSheet(styleSheet) {
try {
// visit every rule in the stylesheet
var cssRules = styleSheet.cssRules;
for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
yield* visitCssRule(cssRule);
} catch (ignored) {}
}
function* findAllMediaRules() {
// visit all stylesheets
var styleSheets = document.styleSheets;
for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
yield* visitStyleSheet(styleSheet);
}
// collect all media rules
const mediaRules = Array.from(findAllMediaRules());
// read scrollbar width
var style = getComputedStyle(document.documentElement);
var scrollbar = style.getPropertyValue('--replace-media-scrollbar') || '15px';
// update media rules
if (scrollbar != '0px') {
var oldValue = '0px';
function updateMediaRulesScrollbar() {
var newValue = window.innerWidth > document.documentElement.clientWidth ? scrollbar : '0px';
// if value changed
if (oldValue != newValue) {
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): (calc\\([^)]*\\)|[^)]*)\\)', 'g');
var replacement = '($1: calc($2 - ' + oldValue + ' + ' + newValue + '))';
mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
console.log(mediaRule);
}
}
oldValue = newValue;
}
updateMediaRulesScrollbar();
window.onresize = updateMediaRulesScrollbar;
}
Optional CSS:
:root {
--replace-media-scrollbar: 15px;
}
A site I'm busy working on has a section with some very large headings. There's something I'm not sure how to handle:
The heading may be one two short or long words, e.g: "Cyprus" to "Nouvelle Zelande", and it must scale to be roughly the width of the viewport. That means "Cyprus", being shorter, will have larger individual characters than longer text than "Nouvelle Zelande".
This would be relatively easy to do with JavaScript, I think, but I'd like to go for a pure HTML/CSS solution. So: how can I scale text to fit the width of the viewport? So far, I'm stumped and not sure how to do it, myself.
Some details:
You only need to target the most recent version of each browser, which includes IE11.
You may use any and all HTML5 and CSS3 that works within those browsers.
It's okay if you make the text "Nouvelle Zelande" word-wrap, as long as the longer of the two words still roughly fits to the width available.
You may add extra elements inside/around the headings.
Note that viewport units are not a solution. Previous questions asking about this (Pure CSS to make font-size responsive based on dynamic amount of characters, Font scaling based on width of container) have answers of "use viewport units, like vw!", but that doesn't handle this scenario at all, and astute readers even pointed this out. I've even used vw in the code sample below to demonstrate its non-solution-ness. It'll size based on the viewport just fine, but won't do any sizing based on the amount of text.
Code sample
h2 {
font-family: sans-serif;
text-transform: uppercase;
font-size: 14vw;
white-space: nowrap;
overflow-x: hidden;
margin: 0;
}
<h2>Nouvelle Zelande</h2>
<h2>Australia</h2>
<h2>Cyprus</h2>
The only unit, if being used to set font size, that is relative to the size of its container, is viewport units vw/vh, which will not solve your case alone, even if the container is the same width as the viewport, since it does not calc the letter size to fit into the container.
The closest non-script solution I can come up with is to use the CSS element counter trick, and wrap each letter in a span
The 130vw I set here, worked best for the given font, though this might need to be adjusted based on which font family is being used.
h2 {
display: inline-block;
font-family: sans-serif;
text-transform: uppercase;
white-space: nowrap;
overflow-x: hidden;
margin: 0;
}
/* 1 letter */
h2 span:first-child:nth-last-child(1) {
font-size: 130vw;
}
/* skipped 2-5 in this demo */
/* 6 letters */
h2 span:first-child:nth-last-child(6),
h2 span:first-child:nth-last-child(6) ~ span {
font-size: calc(130vw / 6);
}
/* skipped 7-14 in this demo */
/* 15 letters */
h2 span:first-child:nth-last-child(15),
h2 span:first-child:nth-last-child(15) ~ span {
font-size: calc(130vw / 15);
}
<h2><span>N</span><span>o</span><span>u</span><span>v</span><span>e</span><span>l</span><span>l</span><span>e</span> <span>Z</span><span>e</span><span>l</span><span>a</span><span>n</span><span>d</span><span>e</span></h2><br>
<h2><span>C</span><span>y</span><span>p</span><span>r</span><span>u</span><span>s</span></h2>
Here is the same concept using a script, and without the span's
(function (d,t) {
window.addEventListener("resize", throttler, false);
window.addEventListener("load", throttler(), false); /* run once on load to init */
function throttler() {
if ( !t ) {
t = setTimeout(function() {
t = null;
keepTextFit(d.querySelectorAll('h2'));
}, 66);
}
}
function keepTextFit(el) {
var f = el[0].getAttribute("data-font");
for (var i = 0; i < el.length; i++) {
var c = el[i].textContent.split('').length;
el[i].style.cssText =
'font-size: calc(' + f + ' / ' + c + ')';
}
}
})(document,null);
h2 {
display: inline-block;
font-family: sans-serif;
text-transform: uppercase;
white-space: nowrap;
overflow-x: hidden;
margin: 0;
}
<h2 data-font="130vw">Nouvelle Zelande</h2>
<h2>Australia</h2>
<h2>Cyprus</h2>
Note, since resize events can fire at a high rate, the throttler is used to reduced the rate so the handler doesn't execute expensive operations such as DOM modifications too often.
If you want to make a perfect fit, check this post: fit-text-perfectly-inside-a-div
If you are looking to use a plugin there's
http://fittextjs.com/
wich can do that for you
I have this code that has one "outerDIV" that contains an "innerDIV". On chrome the "innerDIV" size is 491px, whereas on IE it is 425px (same as outerDIV). Hence, on Chrome I can see the first two children of "innerdiv": "My test string #1" and "test2". But for IE I can only see the first child.
I am not quite sure what the "right" behavior should be, as firefox does the same as IE. However I would like to have IE do the same as Chrome.
I have been experimenting with some css styles (mainly overflow and display), but still can't make it right: IE will expand its height instead of its width to make the elements fit.
Can you guys help me figure out a way to change the css so that IE will wraps the div elements inline? As a restriction though, I cannot change the width on the HTML. As a benefit, I am using a css that only loads for IE to patch these kind of IE inconsistencies. The same css will NOT load for chrome, so I don't need to worry about messing with chrome when changing the IE CSS. Thanks in advance!
<html>
<head>
<style type="text/css">
<!--
body {
font-family: helvetica;
}
.myContainer {
overflow: hidden;
border: 1px solid rgba(0, 0, 0, .5);
font-size: 14pt;
height: 49px;
line-height: 49px;
overflow: hidden;
display: block;
}
.myContainer > DIV {
float: left;
white-space: nowrap;
display: block;
}
.myContainer .item:first-child {
padding-left: 10px;
}
.myContainer .item {
float: left;
padding-right: 32px;
}
-->
</style>
</head>
<body>
<div id="outerDIV" class="myContainer" style="display: block; width: 425px;">
<div id="innerDIV">
<div class="item">
--------My test string #1--------
</div>
<div class="item">
------test2-------
</div>
<div class="item">
test
</div>
</div>
</div>
</body>
</html>
You need a doctype tag on your page, otherwise it will be rendered in quirks mode.
What that means exactly differs from browser to browser, but basically it tries to be compatible with very old browsers. In IE it triggers the non-standard box model, which would explain the differences in size.
Look at the W3C recommended list of doctype declarations for a doctype tag to use.
set the width of .item ... container overflow: hidden hides the items which are shown verticaly because the width is more than a 'line' of container can show. When using floating is good to have the width set. DOCTYPE is very important to be set too. I personaly use loose.dtd which gives good competability.
I could not solve it purely with css. For IE, seems like the only way to fix this is to have the "innerDIV" element to have a width >= the sum of it's children offsetWidth. So I just added this to my JS code (special case for IE):
var len = innerDiv.childNodes.length,
innerDivWidth = 0,
i;
for(i = 0; i < len; i++){
innerDiv += innerDiv.childNodes[i].offsetWidth;
}
innerDiv.style.width = (innerDiv + 1) + 'px'; //Safety measure to make up for the decimal places. I guess we could write this line in a better way by rounding up, etc.
Ill start with showing you my problem in an image:
So i want to make a design for slider, now i want to make buttons for next and previous.
yellow things in image are links with display: block. What do i need to do, to make text ( those arrows are unicode characters ) be positioned vertically and horizontally? Considering i still want whole yellow thing be clickable as a link.
here is how yellow thing looks in css
a.prev {
width: 40px;
height: 270px;
display:block;
float:left;
background: yellow;
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 55px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-bottomleft: 55px;
border-top-left-radius: 5px;
border-bottom-left-radius: 45px;
}
Since you have a fixed height you can use a top margin to push your arrows down to the vertical center.
text-align:center should center your arrow horizontally.
Set line-height equal to the height of the element to center vertically.
I know an answer was accepted already, but I am just giving an alternative and a method that should work on dynamic heights.
I was not sure whether the arrows were merely inside an a ← or inside a span <span>←</span>. When they are not inside a span, it should be added with jQuery.
Static width and height: FIDDLE.
// Add span-wrappers around controls
$("a.controls").each(function() {
$(this.firstChild).wrap("<span></span>");
});
// Position arrows vertically
$("a.controls > span").css("top", function() {
var thisH = $(this).height(),
parentH = $(this).parent().height(),
thisTop = (parentH/2) - (thisH/2);
return thisTop;
});
Now, when you are using a dynamic/fluid lay-out this will not work well because the top-value is only calculated once. We need to recalculate the value every time the window is resized. Take a look here.
// Keep aspect ratio of div
function slideHeight() {
$("#slide-container").height(function() {
var $this = $(this),
w = $this.width() / 2.133;
return w;
});
}
slideHeight();
// Add span-wrappers around controls
$("a.controls").each(function() {
$(this.firstChild).wrap("<span></span>");
});
// Position arrows vertically
function arrowPos() {
$("a.controls > span").css("top", function() {
var thisH = $(this).height(),
parentH = $(this).parent().height(),
thisTop = (parentH / 2) - (thisH / 2);
return thisTop;
});
}
arrowPos();
//Execute functions on resize
$(window).resize(function() {
slideHeight();
arrowPos();
});
There you go. :)
I have an app built on Cordova and on some of my pages I am able to scroll horizontally out of my content into white space.
This is weird as I have nothing there that extends beyond my #wrapper, which is set to width: 100%.
So I was wondering if there was a way I could disable horizontal scrolling in the app altogether?
UPDATE:
Code on page as requested:
body {
background-color: #fff;
font-family:Arial, Helvetica, sans-serif;
color: #b7b8b9;
height: 100%;
width: 100%;
}
iframe{
border: none;
width: 100%;
/*margin-top: 50px;*/
}
#header{
height: 50px;
width: 100%;
}
<body>
<div id="wrapper">
<div id="header">
<div class="headerback">Home</div>
<div class="headerrefresh"><script>var pathname = window.location.pathname;</script><script>document.write('Refresh')</script></div>
<div class="headertitle"><h2>Get the Look</h2></div>
</div><!--HEADER-->
<iframe src="http://www.mbff.com.au/getthelook"></iframe>
</div>
</body>
Try to debug your page in Chrome (webkit) with the exact dimensions of your device. This solves most rendering issues for me.
I do not know the specific issue here, but it looks like one of your elements is flowing outside of the wrapper. You could for example try this in your css:
div.wrapper { overflow: hidden; width: inherit; }
Although it might be a better idea to find out why your page is expanding horizontally?
I was looking for the solution to this problem for a long time.
Finally I solved it in the following way.
I set style for bodyand html tags:
position: fixed;
width: 100%;
height: 100%;
overflow: hidden;
After that I've added div to body and set the style for it:
overflow-y: auto;
height: 100%;
So, I have got fixed body, which contains div with vertical scroll bar.
// Phone Gap disable only horizontal scrolling in Android.
// Add this code in your Phone Gap Main Activity.Initially Declare the variable
private float m_downX;
//Then add this code after loadUrl
this.appView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
// save the x
m_downX = event.getX();
}
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// set x so that it doesn't move
event.setLocation(m_downX, event.getY());
}
break;
}
return false;
}
});
Try adding the following code to your .html file:
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
For the sake of completeness, I thought the answer which makes use of the official method of doing such a thing via the preference tag should be added:
<preference name="DisallowOverscroll" value="true"/>
Supported by Android and iOS according the documentation.
Default: false
Set to true if you don't want the interface to display any feedback when users scroll past the beginning or end of content. On iOS, overscroll gestures cause content to bounce back to its original position. on Android, they produce a more subtle glowing effect along the top or bottom edge of the content.
In my case it was broken styling like below
<body>
<div style="margin-left:5%; width:100%">Content</div>
</body>
which cause div to became horizontally bigger than body. I could see scroll when app run in browser. Set width to 90% (as it was initially intended) fixed the problem.
Generally, as it already pointed out here, enough to find element with wrong style which makes your page expanding horizontally and fix it.
BTW DisallowOverscroll was not helpful in above case.