Auto scale image to fit the rest of device height - javascript

First here is an image of what I looking for:
I want to put a header at the top, a paragraph below the header, and an SVG image below the paragraph. I would like this to scale properly on any sized device (well 320x480 is the smallest I am going to go which is an iPhone4 sized device).
I have the following code:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
<div style="height:100%;position:absolute;top:0;left:0;bottom:0;right:0;">
<div>
<h2>Title</h2>
<p>Some long paragraph will be inserted here</p>
</div>
<div>
<img src="mySvg.svg" /> <!-- This image should scale to fit the remaining of the screen size. -->
</div>
</div>
</body>
</html>
The problem is on a small device there are scrollbars and you need to scroll down to view the rest of the image. I would like it to scale properly so that it fits perfectly into the screen so no scrolling is needed.
EDIT: I am using a framework and as a result of the framework I cannot edit the HTML or BODY tags

Try the approach with flexbox + position tricks.
jsFiddle
.container {
height: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: flex;
flex-direction: column;
}
.container div:last-child {
flex: 1;
position: relative;
}
.container div:last-child img {
position: absolute;
max-width: 100%;
max-height: 100%;
}
<div class="container">
<div>
<h2>Title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<div>
<img src="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg" />
</div>
</div>
Or, use flexbox + background image with size contain.
jsFiddle
.container {
height: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: flex;
flex-direction: column;
}
.container div:last-child {
flex: 1;
background: url("https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg") 0 0 no-repeat;
background-size: contain;
}
<div class="container">
<div>
<h2>Title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<div></div>
</div>

i just gaved the body an min-height and min-width like that it never becommes more small than the phone
.test{
min-height:480px;
min-width: 320px;
background-color: pink;
text-align:center;
display: flex;
flex-direction:column;
justify-content: flex-start;
align-items: center;
padding: 0px 10px;
}
body{
margin:0px;
}
<body>
<div class="test" style="height:100%;position:relative;top:0;left:0;bottom:0;right:0;">
<div class="para">
<h2>Title</h2>
<p>Some long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted hereSome long paragraph will be inserted here</p>
</div>
<div class="test">
<img src="http://lorempixel.com/71/95" /> <!-- This image should scale to fit the remaining of the screen size. -->
</div>
</div>
</body>

Related

How to set width to "fit-content" with additional width?

I want to know how I can set the width of an element to fit-content, but I also want to add some more width. I cannot use padding, I only want to use width. Maybe something like width: fit-content + 50px or something like that?
EDIT:
Example:
.element{
width: fit-content + 50px;
}
It's not possible to use calc() to combine intrinsic and extrinsic units. The only option here is to use padding. Since you said you cannot apply padding to your element, you would need to create a child element to carry these styles.
Here's an example (I've added background to each to visualize)
.acharb-outer {
width: fit-content;
margin: 1rem 0;
background: #ffd166;
}
.acharb-inner {
padding: 0 2rem;
background: #ef476f;
}
span {
background: #06d6a0;
}
<div class="acharb-outer">
<div class="acharb-inner">
<span>Quisque ut dolor gravida.</span>
</div>
</div>
<div class="acharb-outer">
<div class="acharb-inner">
<span>Fabio vel iudice vincam, sunt in culpa qui officia.</span>
</div>
</div>
<div class="acharb-outer">
<div class="acharb-inner">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed.</span>
</div>
</div>

Calculate height of div element based on offsetHeight and clientHeight not working in Css

I want to get the exact div height that contains certain elements within it, I have margins and padding associated with that div.
here HTML:
<div class="main">
<div class="child">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
</p>
<ul>
<li>test</li>
<li>test333</li>
</ul>
<p>
<strong>testststststs</strong>
</p>
</div>
</div>
css:
.main {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
height: 60px;
overflow: hidden;
border: 1px solid #000;
}
.child{
margin: 10px 10px 10px 25px;
font-size: 13px;
line-height: 16px;
}
Js:
var cont = document.getElementsByClassName('main-class')[0];
var child = cont.getElementsByClassName('child')[0];
console.log(cont.clientHeight); //60
console.log(child.clientHeight);//40
console.log(child.offsetHeight);//40
i'm not sure if im getting the correct height for the child as the height seems to be lesser than the parent height- if that is the case why would it truncated as shown here:
https://jsfiddle.net/cudwb2yz/
I want to get the entire height of the div- child document including the content that has been hidden with the overflow:hidden property.
any idea what im doing wrong?

Scrollable text in a DIV of unknown size?

I have this:
<section>
<div id="dont-scroll">
Unknown content!
</div>
<div>
<div id="scroll-this">
This part should be scrollable when
the total content overflows the SECTION
</div>
</div>
</section>
As you can see I want the user to be able to scroll the content in the lower half, but not the upper.
I can achieve this by using "resize" events, checking the size of SECTION and "dont-scroll", etc.
However, is there an easier way today, using only CSS?
A possible approach using Flexbox
body, html {
margin: 0;
padding: 0;
}
section {
height: 100vh;
display: flex;
flex-flow: column nowrap;
}
section > div {
padding: 20px;
}
div:not([id]) {
background: #d8d8dc;
flex: 1;
overflow: auto;
}
<section>
<div id="dont-scroll">
Unknown content! <br />
Lorem ipsum sit dolor amet
</div>
<div>
<div id="scroll-this">
This part should be scrollable when
the total content overflows the SECTION
<br /><br />
<p>Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Donec
odio. Quisque volutpat mattis eros.
Nullam malesuada erat ut turpis.
Suspendisse urna nibh, viverra non,
semper suscipit, posuere a, pede.</p>
...
</div>
</div>
</section>
Example on codepen
Defining height of scroll-this id and using overflow-y: scroll will make scroll-this id scroll able
#scroll-this {
height: 10px; //this can be as per your choice
overflow-y: scroll;
}
I used 10px because your content is too less.
"This part should be scrollable when the total content overflows the
SECTION".
Scroll will show only if line breaking content is greater then provided height.
#scroll-this {
height: 20px;
overflow-y: scroll;
}
<section style="width:200px">
<div id="dont-scroll">
Unknown content!
</div>
<div>
<div id="scroll-this">
This part should be scrollable when the total content overflows the SECTION
</div>
</div>
</section>

Prevent background scrolling when overlay appears

I have written my own modal classes using css and have used it in my application successfully. However the issue i'm facing is when the overlay is open i can still scroll the background contents. How can i stop scrolling background contents when my modal/overlay is open?
This is my modal which opens on top of the overlay
<div>
<div className="overlay"></div>
{this.props.openModal ?
<div>
<div className="polaroid sixten allcmnt_bg_clr horiz_center2">
{}
<div className="mobile_header">
<PostHeader/>
</div>
<div className="mobile_renderPost">
{ this.renderPostType() }
</div>
<div className="mobile_post_bottom"></div>
</div>
</div> : null}
</div>
my overlay css
.overlay {
background-color: rgba(0, 0, 0, .70);
position: fixed;
width: 100%;
height: 100%;
opacity: 1;
left: 0;
right: 0;
-webkit-transition: opacity .25s ease;
z-index: 1001;
margin: 0 auto;
}
One approach is hidden the overflow of the body element.
like this:
body.modal-open{
overflow:hidden;
}
so in this case when you popup the modal you add a class to body and then when you close it you remove that class.
another approach is using a javascript to disable the scroll like this:
document.documentElement.style.overflow = 'hidden';
document.body.scroll = "no";
and then return it with
document.documentElement.style.overflow = 'scroll';
document.body.scroll = "yes";
When you open the modal, you can add overflow: hidden; to the body's style.
Or,
body.modal-opened {
overflow: hidden;
}
And add modal-opened class to the body when opening and remove when you close the dialog.
Using JavaScript to add a class to the body with
overflow:hidden;
will work in most cases, but I beleive Safari on iPhone will still scroll slightly with jitter due to Touch Move and something like this will be needed.
function handleTouchMove(e)
{
e.preventDefault();
}
function lockscreen()
{
var body = document.getElementById("body");
body.className += " lock-screen";
body.addEventListener('touchmove', handleTouchMove, false);
}
function unlock()
{
var body = document.getElementById("body");
body.classList.remove("lock-screen");
body.removeEventListener('touchmove', handleTouchMove);
}
to stop the user from still scrolling
I had this problem too and tried every answer from setting the height on the body element to 100% or 100vh and overflow: hidden. This caused a few issues for me, starting with that using the hidden overflow with the 100vh made the page jump to the top whenever clicking the hamburger menu button.
The solution: adding the overflow:hidden property to the html tag. This worked perfectly where the menu would open, prevent the page from scrolling, and remain where the user is on the page without it jumping.
Since it looks like you're using React, here is an example of how I used it:
.lock-scroll {
overflow: hidden;
}
const [open, setOpen] = useState(false)
useEffect(() => {
const html = document.getElementsByTagName('html')[0]
if (open) {
html.classList.add('lock-scroll')
} else {
html.classList.remove('lock-scroll')
}
return (): void => {
html.classList.remove('lock-scroll')
}
}, [open])
When the modal opens, hide the x/y scroll bars on the body.
.no-scroll {
overflow: hidden;
}
Using JavaScript add the class to the body:
<body class="no-scroll">
</body>
Once you close the modal remove the class.
Combining the overflow: hidden solution with modern technique works perfectly
html:has(dialog[open]) {
/* remove the main scrollbar when dialog is open */
overflow: hidden;
}
All the answers so far (Oct. 2022) suggest to add overflow: hidden dynamically to either 'body' or 'html' when you open the modal/pop-up. This works if 'html' or 'body' are actually your scrolling elements and fixes the somewhat counterintuitive over-scroll behavior of position: fixed elements.
I've tried to use overscroll-behavior instead to fix the issue and this can work, but requires scrollable elements (with actual overflow) inside your modal and is not very reliable if the user simply decides to touch your overlay outside of the "locked" elements.
Depending on your page design there is another option that requires you to split content and overlay and set the 'html' and 'body' height explicitly to 100%. Here is a complete example:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
box-sizing: border-box;
}
body {
position: relative;
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
}
.content {
padding: 32px;
border: 1px solid #000;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, .5);
backdrop-filter: blur(5px);
display: flex;
justify-content: center;
align-items: center;
z-index: 1001;
}
.info-box {
background: #000;
color: #eee;
border-radius: 5px;
width: 240px;
height: 240px;
padding: 16px;
}
/* scroll fix */
html, body {
height: 100%;
}
.content {
max-height: 100%;
overflow-y: auto;
}
</style>
</head>
<body>
<div class="content">
<h2>Overlay Background Scroll Test</h2>
<p>Use a window size of around 320x480 for optimal testing (e.g. via device-toolbar).</p>
<h3>Scrollable Page</h3>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<button onclick="document.querySelector('.overlay').style.display='flex';">open</button>
</div>
<div class="overlay">
<div class="scroll-fix">
<div class="info-box">
<h3>Pop-Up Message</h3>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
<button onclick="document.querySelector('.overlay').style.display='none';">close</button>
</div>
</div>
</div>
</body>
The important section is the last CSS entry. This will make your .content element the main scroll element:
html, body {
height: 100%;
}
.content {
max-height: 100%;
overflow-y: auto;
}
There is a disadvantage to this approach though. Most mobile browsers will not be able to automatically hide their URL-bar through scrolling anymore, because this seems to depend on html or body element scrolling :-(.

Flexbox text cutting off/not wrapping

I'm using flexbox to display a blockquote and author/avatar horizontal to each other. This is within a slideshow (flexslider) but that doesn't seem to be the reason for the problem.
This works ok until we hit IE10. It appears to work fine in Chrome, Firefox, Opera, Safari, Edge and IE11.
The problem I'm having is the text is cut off at the end of the quote. If you don't see this at first you may have to resize your viewport. This may be caused by the padding I have at each side of the text to allow space for the custom open/close quotation marks.
Another issue in IE10 is that when the text is long (see "James Hetfield Longname" on the first quote) it doesn't wrap. This could be related to my other issue as I guess the text isn't wrapping correctly then either.
Here's some links to an example. I've include a CodePen and also a stripped back version of my HTML template.
CodePen: http://codepen.io/moy/pen/XdLELV
Template: http://moymadethis.com/flex/quote.html
Really hope someone can help with this!
Here's the code, as it's making my add something (though I don't think this wall off CSS/HTML is particually helpful myself)!
EDIT: I should add that I use Autoprefixer to popular the extra flex prefixes.
HTML:
<div class="flexslider">
<ul class="slides">
<li>
<blockquote class="feature-quote">
<p class="feature-quote__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</p>
<footer class="feature-quote__cite">
<img src="img/temp/avatars/avatar-james.jpg" class="feature-quote__avatar" />
<p><strong class="name">James Hetfield Hetfield</strong> Damage Inc.</p>
</footer>
</blockquote>
</li>
<li>
<blockquote class="feature-quote">
<p class="feature-quote__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</p>
<footer class="feature-quote__cite">
<img src="img/temp/avatars/avatar-james.jpg" class="feature-quote__avatar" />
<p><strong class="name">James Hetfield</strong> Damage Inc.</p>
</footer>
</blockquote>
</li>
<li>
<blockquote class="feature-quote">
<p class="feature-quote__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</p>
<footer class="feature-quote__cite">
<img src="img/temp/avatars/avatar-james.jpg" class="feature-quote__avatar" />
<p><strong class="name">James Hetfield</strong> Damage Inc.</p>
</footer>
</blockquote>
</li>
</ul>
</div>
CSS:
/* Base blockquote styles */
blockquote {
margin-bottom: $baseline*2;
overflow: hidden; // Fixes bug when inside flexslider when open/close quote-marks duplicate.
padding: $baseline $baseline 0 0;
p {
margin-bottom: $baseline/2;
}
> p {
color: $blue-light;
#include font-size(25);
line-height: $baselineheight/1.25;
font-weight: 300;
padding-left: 30px;
-webkit-font-smoothing: antialiased;
&:before,
&:after {
background: url(../img/content/quote-open.png) no-repeat 0 0;
content: "";
display: inline-block;
height: 24px;
margin: 0 10px 0 -30px;
position: relative;
top: -5px;
width: 21px;
}
&:after {
background: url(../img/content/quote-close.png) no-repeat 0 0;
margin: 5px 0 0 5px;
position: absolute;
top: auto;
}
}
footer {
padding-left: 30px;
}
.name {
color: $blue;
display: block;
text-transform: uppercase;
}
}
/* Feature (avatar) quotes */
.feature-quote {
margin-bottom: $baseline;
padding-top: 5px;
}
.feature-quote footer p {
display: inline-block;
margin-bottom: 0;
vertical-align: middle;
}
.feature-quote__cite {
margin-top: $baseline;
}
.feature-quote__avatar {
border: 5px solid $blue-lighter;
border-radius: 100%;
display: inline-block;
height: 60px;
margin-right: $baseline/2;
width: 60px;
}
/* Above 768px (Feature quote side-by-side */
#media only screen and (min-width: 768px) {
blockquote {
margin: 0 25px $baseline*2;
}
.feature-quote {
display: flex;
}
.feature-quote__text {
order: 2;
width: 66.66666%;
}
.feature-quote__cite {
display: flex;
align-items: center;
justify-content: center;
order: 1;
margin-top: 0;
padding-right: 30px;
width: 33.33333%;
}
.feature-quote__avatar {
height: 80px;
width: 80px;
}
.no-flexbox {
.feature-quote {
margin: 0 auto $baseline;
max-width: 800px;
}
.feature-quote__text,
.feature-quote__cite {
text-align: center;
width: 100%;
}
.feature-quote__cite {
p {
text-align: left;
}
}
}
}
Expanding upon Pete's comment about IE10 not properly supporting flexbox.
http://caniuse.com/#search=flex
Regarding IE10:
Only supports the 2012 syntax
Need the -ms- prefix
This answer actually has lots of information about flex in IE10: https://stackoverflow.com/a/21306343/2117156
Note I'm using autoprefixer so all -ms- prefixes are generated automatically. I will just note the prefix-less declarations here.
Adding the following line onto the paragraph did the trick flex: 0 1 auto;
I also had an issue where the text wouldn't wrap in the .feature-quote__cite container. I tried adding the above which didn't work. To fix this I had to add flex: 0 1 auto; directly onto the paragraph within rather than on the parent container .feature-quote__cite. Not ideal but it looks like it's done the trick.
As an aside, in IE11 the avatar image would get squashed when there wasn't enough horizontal space. I found adding flex-shrink: 0; to the image fixed this.

Categories