Context:
I'm working on the PDF viewer using react-pdf and one of the issues I've stumbled upon is zooming. Let's say we've rendered 3 pages (800x1100px), our initial scale factor is 1 and we've scrolled to the middle of the overflown container.
Each page is being rendered within a wrapper that takes into account current scale factor like this.
return (
<div ref={ref} css={styles.page} style={{
width: viewerScale * initialPageWidth,
height: viewerScale * initialPageHeight,
left: '50%',
transition: 'all .2s ease-in`,
transform: `translate(-50%, ${topOffset}px)`,
marginBottom: 12,
bottom: 0,
position: 'absolute',
top: 0
}}>
{pdfPage}
</div>
)
})
Wrappers reside within overflown div with the following styles:
height: 100%;
padding: 80px 0;
width: 100%;
overflow: auto;
position: absolute;
I'm not using scale prop provided by react-pdfs Page component as rerendering is quite slow once you have more than 100 pages. Instead I render page once in the highest resolution and rely on the combination of width & height making it sort of responsive.
Once scale factor changes each page is being re-rendered and animated to imitate scaling experience. That being said, I'm experiencing couple of issues:
Initial scrolling position is not preserved due to the change to the total height of overflow container.
Pages are not being scaled with respect to the scroll position which causes scroll jumps.
Question
How does one scale content while preserving scroll position in a Google-like fashion?
I've been trying to reverse-engineer their solution to some extent and I've managed to get ​pretty close by using transform: scale on the overflow container and changing its transform-origin dynamically based on the scroll position.
That being said, it causes flickering once the user scroll fast and causes a lot of repaints which are quite expensive. My understanding is that Google's viewer relies on a combination of container width and padding-bottom attributes in conjunction with absolutely positioned items but I'm absolutely clueless as to how they achieve their scaling effect.
Please let me know if you need me to provide any additional details and thanks in advance!
Related
So I want to have a central div that is full screen, and to make the width and height of the body 150 vw and vh, with a margin of 50% so when you load the page it holds the div central, but you can scroll up, down, left, right, outside of this central div a little bit.
If you do the div 100vw, 100vh, and then the body 200vw, 200vh, it only enables scrolling to the right and downwards.
This is my understanding of how to get towards what I'm trying to do:
HTML:
<div>
centered and full screen div?
</div>
</body>
CSS:
body{
width:150vw;
margin-left:50vw;
height:150vh;
margin-top:50vh;
}
div{
width: 100vw;
height: 100vh;
border: solid;
}
JAVA:
window.scrollTo(50 + 'vw', 50 + 'vh');
https://jsfiddle.net/dsLnzyxw/3/
But this doesnt work as the javascript doesn't accept vw in the scrollTo function.. but just to give a better idea of what I'm trying to do.
Also understand I might be going around on crazy route trying to achieve something that could be done quite simple in css?
How do I achieve this?
Thanks !
In order to get units relative to the viewport width and viewport height (vw and vh) you could do simple calculations:
window.scrollTo(0.5 * window.innerWidth, 0.5*window.innerHeight);
which would set the scroll position to 50% of the window width and 50% of the window height. window.innerWidth returns the width of the window, and this is multiplied by 50% to get 50% of the width of the window in pixels.
The same goes for height. Setting the scroll position is not possible without JavaScript unfortunately.
REFERENCE: http://www.templatewire.com/preview/landscaper/
I want to make a web page, and in that page, I want to have divs/sections each the size of the screen.
Now, I mean, the width and height of the monitor, and it won't resize again, and will stay the width and height of that monitor, regardless of the browser size, and regardless of how much content is inside it.
The link shows you what I mean, but I have a 1920x1080 browser window, you can see the top and bottom of the sections above and below it. I don't want the top and bottom of neighbouring sections to be seen if the monitor is very big, nor do I want the section to not be fully visible if the monitor's too small.
Example, say I had 5 sections like in the reference, and my browser window was 1920x1080, the overall height of that document would be 1920*5400.
(I want it to be the height of the screen minus the height on the nav bar.)
You can use Viewport units (the browser window size). 100vh is the height of the screen. If you got sections that bigger than the height of little screen you can use the min-height property and set it to 100vh.
Since you didn't place your code, this is generally example of use case:
section { min-height: 100vh;}
Read more here:
https://developer.mozilla.org/en-US/docs/Web/CSS/length
Good luck!
It appears you're looking for viewport percentage lenghts.
To give any element current viewport's height, in CSS, one should use:
your-selector {
height: 100vh;
display: block;
}
If the element is a <div> or any other element with a default value of block for display, it obviously doesn't need the second rule.
See it working:
your-selector {
height: 100vh;
display: block;
transition: background-color .3s linear;
}
/* let's add a hover, for testing */
your-selector:hover {
background-color: red;
}
body {
margin: 0;
min-height: 200vh;
}
<your-selector>Test</your-selector>
Note: you can also apply viewport percentage lengths to other properties, such as min-height, max-height, etc...
Note: although default viewport is browser window, that's can change. For example, 3d transforms turn any regular DOM element into a viewport for their children, affecting behavior of viewport percentage lengths, as well as behavior of position:fixed in any of their children.
I'm working on a component that transitions an image from a start position + scale to an end position + scale (i.e. to fill up the screen). This is done with a CSS transform animation on translate and scale.
The challenge is that some of the images to transition from may be altered by component users using the object-fit property. However, it appears that the CSS translate does not maintain the object-fit property during translate.
Codepen example here: https://codepen.io/cathyxz/pen/mXgEMB
I know I could technically animate width and height, but I want to keep in line with properties that browsers can animate cheaply for performance reasons, i.e. nothing that affects layout, which leaves us with only position, rotation, scale, opacity.
References: https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
Is there anyway I can gradually animate my transition to "uncrop" images instead of stretching them?
object-fit is applied to the element before transformation.
Whatever the outcome of all CSS on the object, transform takes it and applies the transformation. In fact, the element is left in DOM untouched. That's why transform does not trigger a repaint (and is considered performant). Only its rendering (the composite layer) is transformed. Its rendering is stretched 4 times on X axis because of the transform. But this does not make the element 4 times wider and therefore object-fit cannot apply as you expect.
Can you gradually uncrop? Yes, but not with transform. In order to do it as cheap as possible (without triggering a repaint on subsequent flow) you need:
A parent placeholder (with position:relative) as tall as your image, to keep the space free in document flow
The element to be animated, with position:absolute. Because of this, even if you animate width, you do not trigger layout, because the element is outside of document flow.
.transform-placeholder {
height: 100px;
position: relative;
}
.transform-placeholder .object-fit {
width: 100px;
height: 100px;
animation: object-fit 2.1s infinite;
animation-timing-function: cubic-bezier(.4,0,.2,1);
}
#keyframes object-fit {
0% {
width: 100px;
}
50% {
width: 400px;
}
100% {
width: 100px;
}
}
<div class="transform-placeholder">
<div class="object-fit" style="background-image: url('https://picsum.photos/1600/400?image=857')">
</div>
</div>
<h2>Animation above does not trigger repaint on any DOM element that's outside the animated div.</h2>
I am trying to create a responsive design for my app.
I have a big background image and it will show the full size when user has large screen and only show partial if user uses small screen.
I want to place few elements on my app with absolute position but the problem is I can't lock their top and left value because the screen size changes.
I have something like
css
#background{
background: url('BG.jpg') no-repeat top center fixed;
width: 1900px;
height: 1200px;
}
#element{
position: fixed;
z-index: 5;
top: 50%; //looks fine in 1900 x 1200 screen but position is off on 1200 x 1000
left:70%; //looks fine in 1900 x 1200 screen but position is off on 1200 x 1000
}
html
<div id='background'></div>
<img id='element' src='test.jpg' />
How do I keep the position of the element on the same spot when user has small screen? Thanks for the help!
When using position: absolute, you need to make sure that it has a parent with a position attribute other than the default (which is static). If there is no such parent, the document is the effective parent. For your example, I would advise making the img#element a child of div#background like so
<div id='background'>
<img id='element' src='test.jpg' />
</div>
and then adding position:relative; to the #background css style
#background{
background: url('BG.jpg') no-repeat top center fixed;
width: 1900px;
height: 1200px;
position: relative;
}
The reason relative is used, is because it doesn't take the element out of the document flow (like fixed or absolute would) and as long as you don't specify a top, left, 'bottom', or right attribute to the parent (#background in the case), it will stay in the same location as it would with default positioning.
Edit:
I don't think this will work out of the box for you. You need to figure out how to make the image's width dynamic as well. You can either give it a % based width or use media queries.
Edit 2:
Ia also just noticed you have position:fixed for img#element. Change that to position:absolute. that will make it so that it is positioned relative to the position:relative parent rather than the window.
Consider making a javascript function that calculates the screen width. After that add margin-left to #background equal to ( screen width / -2 ). Make #background width & height - 100%
I'm having a hard time with a diagonal background image. This is not a "pattern", but a full image used in two types of layouts. (Image: http://i.imgur.com/mcWseu1.jpg)
On one template, the image should remain fixed on the page at 100%
height, positioned to the top right and scrolls with the page.
On the second template, the image should maintain the same aspect
ratio as it would in template one, but it should not be fixed.
Instead, it should scroll up with the rest of the page.
I've been able to achieve the desired result for template one, but I'm having a hard time with template two.
Is Javascript the only solution here? If so, any recommendations? Again, the challenges I can't fix:
Get the image to maintain the same aspect ratio as it would in template one (if it's 100% height to fit the window in template one, then it should size at 100% height in template two with the exception of being fixed) This is to maintain consistency between pages using separate templates.
Thanks for the help.
Edit: I have no code to reference for the actual challenge I'm facing. But here is the solution I've found for the first template:
CSS (applied to an img element):
.abovefold {
width: auto;
height: 100%;
position: fixed;
top: 0;
z-index: -1;
}
I believe you're looking for the CSS background-attachment attribute. To fix a background, simply set it as such:
.example {
background-image: url('http://i.imgur.com/mcWseu1.jpg');
background-attachment: fixed;
}
http://www.w3.org/community/webed/wiki/CSS_shorthand_reference#Background
I've demonstrated this in a fidde: http://jsfiddle.net/GHDbM/
When it comes to dimensioning the background, you'll want to set the background-size attribute:
.example {
background-size: auto 100%; /* Adjust to element height */
}
The auto in the above example is for width and the 100% is for height.
http://www.w3.org/TR/css3-background/#the-background-size
Another fiddle for this: http://jsfiddle.net/sk2RY/