I am currently working with Vuejs and routing to other pages. For my link to photos, I would like a main cover photo that covers the entire screen.
<template>
<div id="album-container">
<div class="cover-image"></div>
<section class='intro'>Lorem </section>
<div class="image-flex-wrap">
<div class="image-cell" v-for="image in images">
<img :src="image">
</div>
</div>
</div>
</template>
.cover-image {
background: url('my photo') #fff no-repeat center center;
background-size: cover;
height: 100vh;
}
This displays the page the way I want it, but the problem arises when I am routed to this page from a page where I have previously scrolled down. Instead of starting at the top of the page, it begins around the middle of my cover-image div. I believe the problem has something to do with the height: 100vh because if I replace it with position: absolute and a width of 100%, then the page will start at the top. However, I would like to refrain from using absolute positioning but don't know enough css to understand why this is occurring.
Thanks for the suggestions.
The issue turned out to be unrelated to Vuejs. I had failed to mention I was using Material Design Lite since I didn't expect it to be the cause but unfortunately it was. Due to the way it works, you no longer scroll on the window object by rather the .mdl-layout__content class supplied by MDL. This was why all scroll properties relating to window was returning 0.
I simply set up a watch method on my routes to force scrollTop.
watch: {
$route() {
document.getElementsByClassName('mdl-layout').scrollTop = 0;
}
}
It can probably be related to scrollBehaviour of your vue-router config as well, try to add following scrollBehaviour in the config:
export default new Router({
mode: 'history',
scrollBehavior: (to, from, savedPosition) => {
if (to.hash) {
return {selector: to.hash}
} else {
return {x: 0, y: 0}
}
},
routes: [
{ path: '/', component: landingView },
....
....
{ path: '/healthcheck', name: 'healthcheck', component: healthCheckView }
]
})
Related
I am working on a website and on some pages there are very few contents like login page and footer don't reach to bottom, That's why I want main section to cover remaining space if there is any and work like normal if overflow. Basically I want it to work like min-height. I tried using min-height with 100vh and 100% but no desired result.
You can use a custom min height.
<div class="min-h-60">
content...
</div>
In our tailwind config file, you should extend minHeight:
module.exports = {
purge: [],
theme: {
extend: {
minHeight: {
'60': '15rem'
}
}
},
variants: {},
plugins: []
}
Basically, I'm creating a form component that is contained inside a v-dialog. The form component will have different child components that are rendered based on select input. So I have to set width of v-dialog to "unset", so that the width of the dialog will stretch to match its content.
The transition works when I toggle the value of width, eg: either 450px or 300px. The problem is that I don't know beforehand the width of the form contains in the dialog, so I definitely need to use dynamic width.
So far, I can not find anyways to achieve transition when using dynamic width. I was trying to get the width of the form component using refs, but setting width to unset, prevent the transition. By the way, the transition I'm talking about is the transition of the width, when using fixed width, it shows nice transition but not for dynamic width
<div id="app">
<v-app id="inspire">
<div class="text-center">
<v-dialog v-model="dialog" width="unset">
<template v-slot:activator="{ on }">
<v-btn color="red lighten-2" dark v-on="on">
Click Me
</v-btn>
</template>
<v-card>
<v-select v-model="selectedForm" :items="items">
</v-select>
<div v-if="selectedForm==='form-a'" class='form-a'>FormA</div>
<div v-if="selectedForm==='form-b'" class='form-b'>FormB</div>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" text #click="dialog = false">
I accept
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</v-app>
</div>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
selectedForm: "form-a",
items: ["form-a", "form-b"],
dialog: false
};
}
});
codepen for using fixed width: https://codepen.io/duongthienlee/pen/MWaBLXm
codepen for using dynamic width: https://codepen.io/duongthienlee/pen/GRpBzmL
Noted that in the example i made in codepen, I defined width already, but the real case is that I don't know beforehand the width of form-a and form-b component. form-a and form-b width will be inherited by its parent div which is v-dialog, so that's why I set the width of v-dialog to be unset.
An example of what I mean "dynamic width": form-a has a select input. When user chooses an item, there will be a request to server to get input labels. So form-a will render multiple input fields based on the response body from server. The response body will contain label and default values information. So that makes the width of form-a becomes dynamic.
I think something like this can work for you.
Change v-dialog like so:
<v-dialog v-model="dialog" :width="forms.find(x => x.name===selectedForm).width">
Modify data() to return a forms prop:
data() {
return {
selectedForm: "form-a",
items: ["form-a", "form-b"],
dialog: false,
forms: [
{
name: 'form-a',
width: 200
},
{
name: 'form-b',
width: 1000
}
]
};
}
What you want to do is get the size of the rendered form, and then apply it to the dialog.
This is a common theme when attempting to animate content with dynamic dimensions.
One way to do this is by:
Set the form's visibility as hidden
Wait for it to render
Get the form's width and set it to the dialog
Unset the form's visibility
The tricky/hacky part is that you have to properly await DOM (setTimeout) and Vue ($nextTick) recalculations. I didn't have to await for Vue's $nextTick in this example, but you probably will if you're rendering nested form components:
<div class="form-container">
<div :style="formStyle('form-a')" class='form-a' ref="form-a">FormA</div>
<div :style="formStyle('form-b')" class='form-b' ref="form-b">FormB</div>
</div>
computed:{
formStyle(){
return form => ({
visibility: this.selectedForm == form ? 'inherit' : 'hidden',
position: this.selectedForm == form ? 'inherit' : 'absolute'
})
}
},
methods: {
async onSelectChange(form){
// async request
await new Promise(resolve => setTimeout(resolve, 1000))
this.selectedForm = form
this.recalculate()
},
async recalculate(){
// wait for DOM to recalculate
await new Promise(resolve => setTimeout(resolve))
const formEl = this.$refs[this.selectedForm]
this.dialogWidth = formEl.clientWidth
this.dialogHeight = formEl.clientHeight
},
...
}
Here's the working code to give you an idea:
https://codepen.io/cuzox/pen/yLYwoQo
If I understand you correctly, then this can be done using css. You can try replace all the fix width in the form with
width: fit-content;
For example in you codepen:
.form-a {
width: fit-content;
height: 350px;
background: blue;
}
.form-b {
width: fit-content;
height: 500px;
background: red;
}
The v-dialog renders into a div with class v-dialog:
It seems the animation only works when the the width is of known value, so it cannot be just "unset". The solution would be to get the width of the child element, and set the width of the v-dialog accordingly with a variable.
See VueJS get Width of Div on how to get the width of the child element.
Let me know if it works, I find this is very interesting.
I am using react-monaco-editor but I am not able to make it responsive. It takes a fixed height and width in the components. If I change the screen size, the width stays fixed.
<MonacoEditor
width="1200"
height="600"
language="typescript"
theme="vs-dark"
defaultValue="//type your code here"
value={code}
options={options}
onChange={this.onChange}
editorDidMount={this.editorDidMount}
className='editor1'
/>
If I remove the width and height from the component, the component diminishes. I tried overriding the component className with flex. But it doesn't seem to work well.
.react-monaco-editor-container {
flex: 2;
}
Can you help me with the CSS to make this responsive?
Simply in options set automaticLayout: true
You could add a resize handler in order to figure out the available space for your editor container and pass it to your Monaco Editor right away.
There are as well different libraries that assist you with that:
https://www.npmjs.com/package/react-resize-detector
Here you can find a Sandbox example with using the library above:
https://codesandbox.io/s/vibrant-goldwasser-3d8j7?fontsize=14&hidenavigation=1&theme=dark
import React from "react";
import { withResizeDetector } from "react-resize-detector";
const Editor = ({ width, height }) => (
<div
style={{
background: "grey",
height: height,
width: width
}}
>
Editor container with {width} x {height}
</div>
);
export default withResizeDetector(Editor);
After a few things didn't work with CSS, I tried javascript to solve this
updateDimensions = () => {
this.setState({
width: window.innerWidth - 501,
height: window.innerHeight - 50,
});
};
componentDidMount() {
window.addEventListener("resize", this.updateDimensions);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions);
}
Storing the height and width in the state and changing on resize event did the job.
I am using Puppeteer v1.6.0 and headers and footers are not displayed on the first page when creating a PDF with the displayHeaderFooter:true option, any idea how to enable this?
According to the Puppeteer Documentation:
page.pdf(options)
options <Object> Options object which might have the following properties:
displayHeaderFooter <boolean> Display header and footer. Defaults to false.
headerTemplate <string> HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them:
date formatted print date
title document title
url document location
pageNumber current page number
totalPages total pages in the document
footerTemplate <string> HTML template for the print footer. Should use the same format as the headerTemplate.
margin <Object> Paper margins, defaults to none.
top <string> Top margin, accepts values labeled with units.
right <string> Right margin, accepts values labeled with units.
bottom <string> Bottom margin, accepts values labeled with units.
left <string> Left margin, accepts values labeled with units.
returns: <Promise<Buffer>> Promise which resolves with PDF buffer.
NOTE Generating a pdf is currently only supported in Chrome headless.
NOTE headerTemplate and footerTemplate markup have the following limitations:
Script tags inside templates are not evaluated.
Page styles are not visible inside templates.
Therefore, make sure that you are using the displayHeaderFooter, headerTemplate, and footerTemplate options appropriately to allow for proper PDF generation.
Also, make sure that you set the font size of the header and footer via CSS (you may need to use inline CSS), and set the margin option of the web page to ensure that the content of the web page does not cover up the header and footer.
Example:
await page.pdf({
path: 'example.pdf',
displayHeaderFooter: true,
headerTemplate: '<div id="header-template" style="font-size:10px !important; color:#808080; padding-left:10px"><span class="date"></span><span class="title"></span><span class="url"></span><span class="pageNumber"></span><span class="totalPages"></span></div>',
footerTemplate: '<div id="footer-template" style="font-size:10px !important; color:#808080; padding-left:10px"><span class="date"></span><span class="title"></span><span class="url"></span><span class="pageNumber"></span><span class="totalPages"></span></div>',
margin: {
top: '100px',
bottom: '200px',
right: '30px',
left: '30px',
},
});
thanks a lot! the problem was that i didn't only have to set the margin in puppeteer but also in the actual page!still does not make a lot of sense to me why it headers/footers were displayed on all of the pages but on the first, but anyway, this was the solution...
I used jsreport for render pdf in nodejs. I have a problem with headerTemplate and footerTemplate don't render when I generate my pdf. There is a lot of code sample to use
'margin': {
top : '100px',
bottom : '200px',
right : '30px',
left : '30px'
}
but it doesn't work for me. I keep searching for two days until i go to see the unitesting for chrome-pdf. here the link https://github.com/jsreport/jsreport-chrome-pdf/blob/master/test/chromeTest.js.
It saw the code as below and it works for me. I need to use marginTop and marginBottom instead of margin object.
const resp = await jsreport.render({
template: {
content: '{#asset src/storages/htmls/pdf/master-card.html}',
engine: 'handlebars',
recipe: 'chrome-pdf',
pdfPassword: {
active: true,
password: '1234'
},
chrome: {
displayHeaderFooter: true,
headerTemplate:'',
footerTemplate:`<h1>Page <span class="pageNumber"></span> of <span class="totalPages"></span></h1>`,
format : 'A4',
marginTop: '80px',
marginBottom:'80px'
},
//javascript helper functions used by templating engines
helpers: helper
},
I solved the problem by adding the margins. The Header and Footer was under the page.
margin: {
top: '100px',
bottom: '200px',
right: '30px',
left: '30px',
},
Well... I need to look for the original margins values. Took some time and found chrome's default mating:
margin: {
top: '0.39in',
left: '0.39in',
bottom: '0.38in',
right: '0.38in',
},
I have the following css:
html, body {background:#ebeced;min-height:100%;font-family:Helvetica}
body {overflow-y:scroll; cursor:default;}
And I add the .fixed class dynamically to the body when I open a modal window so that scrolling can't take place.
.fixed #container-wrapper {position:fixed;left:0;width:100%;}
I also have a fixed nav bar and then the content. The content is inside container-wrapper:
<body>
<nav></nav>
<div id="container-wrapper">
<!-- all website content -->
</div>
</body>
Problem
If I have scrolled down through the content at all and then open the modal, the content jumps right back to the top. I thought this may be an issue with event.preventDefault but I know now that it isn't to do with this. It's connected to the adding of the .fixed class that causes the issue.
JSFIDDLE
https://jsfiddle.net/w9w9hthy/1/ - scroll down to the button and click the button. This will add a .fixed class and the content will "reset" to the top. How can I stop this "reset" effect?
Instead of making container-wrapper fixed you can stop scrolling from happening by making the body overflow: hidden and removing it when you want scrolling to continue.
Fiddle: https://jsfiddle.net/w9w9hthy/2/
.fixed {
overflow: hidden;
}
Demo: https://jsfiddle.net/w9w9hthy/5/
From my jQuery popup project: https://github.com/seahorsepip/jPopup
//Freeze page content scrolling
function freeze() {
if($("html").css("position") != "fixed") {
var top = $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop();
if(window.innerWidth > $("html").width()) {
$("html").css("overflow-y", "scroll");
}
$("html").css({"width": "100%", "height": "100%", "position": "fixed", "top": -top});
}
}
//Unfreeze page content scrolling
function unfreeze() {
if($("html").css("position") == "fixed") {
$("html").css("position", "static");
$("html, body").scrollTop(-parseInt($("html").css("top")));
$("html").css({"position": "", "width": "", "height": "", "top": "", "overflow-y": ""});
}
}
This code takes, width, height, scrollbar and pagejump issues into consideration.
Possible issues resolved with above code:
width, when setting position fixed the html element width can be smaller then 100%
height, same as above
scrollbar, when setting position fixed the page content no longer has a scrollbar even when it had a scrollbar before resulting in a horizontal pagejump
pagejump, when setting position fixed the page scrollTop is no longer effective resulting in a vertical pagejump
If anyone has any improvements to above page freeze/unfreeze code let me know so I can add those improvements to my project.
Edit:
Just tested above code on some random pages and found some issues on some sites due to the use of body or html as main scroll content, I resolved those issues in above code and will push them to the github project.