Preventing fancybox returning to top of page - css

In my website, I am using fancybox 2.1.5. when I open an image and close it I return to the top of the page unintentionally. The problem can be seen in the following minimal example
<!DOCTYPE html>
<head>
<style media="screen" type="text/css">
body {
height: 100%;
}
html {
height: 100%;
}
</style>
<link rel="stylesheet" type="text/css" href="css/jquery.fancybox.css?v=2.1.5" media="screen" />
</head>
<body>
<a href=#>
<img src="http://placehold.it/1000x600">
</a>
<a class="fancybox" href="img/Gallery/500x600.gif">
<img src="http://placehold.it/500x600">
</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.fancybox.js?v=2.1.5"></script>
<script>
$(document).ready(function() {
$('.fancybox').fancybox();
});
</script>
</body>
</html>
You will see that if you open and close the second image you will find yourself at the top of the page.
It appears that if I delete the initial style in the head
<style media="screen" type="text/css">
body {
height: 100%;
}
html {
height: 100%;
}
</style>
The problem disappears. if I erase only the body style or the html style the problem also disappears. In order for the problem to appear both body and html heights must be to 100%
Unfortunately I don't understand why this is happening. Can someone please explain?
Note: I have found solutions and hacks to this problem but I would like to understand why this is happening

Update: seems not to work if you trigger the Fancybox while on a URL that points to a tag with an ID (e.g., "https://example.com/#currentsection"). When you exit the Fancybox, it doesn't go to the top of the page, but does scroll to the top of the tag with the ID, even if you've set the autoFocus and placeFocusBack options to false. Strangely, it still works if your URL is pointed at #top.
Original answer
I found that when using Fancybox in Next.js, binding or configuring Fancybox with autoFocus set to false fixed this. It then seems that placeFocusBack property (default: true) will apply. Set it up like so:
npm install --save #fancyapps/ui
components/fancybox-wrapper.js:
// Fancybox UI wrapper for lightbox
// Thanks to https://fancyapps.com/docs/ui/fancybox/react
import React, { useEffect } from "react";
import { Fancybox as NativeFancybox } from "#fancyapps/ui/dist/fancybox.esm.js";
function Fancybox(props) {
const delegate = props.delegate || "[data-fancybox]";
useEffect(() => {
const opts = props.options || {};
NativeFancybox.bind(delegate, opts);
return () => {
NativeFancybox.destroy();
};
}, []);
return <>{props.children}</>;
}
export default Fancybox;
pages/_app.js:
import Fancybox from "../components/fancybox-wrapper";
import "#fancyapps/ui/dist/fancybox.css";
import { SSRProvider } from "#react-aria/ssr";
function MyApp({ Component, pageProps }) {
return (
<SSRProvider>
<Fancybox options={{ infinite: false, autoFocus: false }}>
<Component {...pageProps} />
</Fancybox>
</SSRProvider>
);
}
export default MyApp;

You can use native helper of fancy box to fix returning to top of page problem.
$('.fancybox').fancybox({
padding: 0,
helpers: {
overlay: {
locked: false
}
}
});
reference : http://davekiss.com/prevent-fancybox-from-jumping-to-the-top-of-the-page/

Related

katex math is not rendering perfectly in react

React code
import React from "react";
import katex from "katex/dist/katex.mjs";
export default function App() {
return (
<div
dangerouslySetInnerHTML={{
__html: katex.renderToString("\\sum_{i=0}^{n-1}A[i]"),
}}
/>
);
}
/public/index.html
Included style
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex#0.13.18/dist/katex.min.css" integrity="sha384-zTROYFVGOfTw7JV7KUu8udsvW2fx4lWOsCEDqhBreBwlHI4ioVRtmIvEThzJHGET" crossorigin="anonymous">
Output
Expected output
Can anyone tell me that what mistake is here?
Answer to my question
const html = katex.renderToString(str, {
throwOnError: false,
displayMode: true // make it true
})
.katex-display,.katex-display > .katex, .katex-display > .katex > .katex-html {
display: inline !important;
// make it inline, so it can render with your text even after `displayMode:true`
}
.katex-display{
text-align:left !important;
}
.katex-display>.katex{
text-align:left !important;
}

CSS flexbox styles to fill width and height of elements

I am creating a web application for my react-native application. I feel quite comfortable in styling on react-native and was trying to use flexbox on the web also hoping it would allow me to use my react-native knowledge. But the styles behave a little differently on the web and I am having a hard time finding a good resource that explains the basics. I understand the meaning of each flexbox properly but there is a gap in my understanding due to which I am not able to achieve the desired layout.
Please refer to the following code snippet. Link to code sandbox also below the snippet.
import React, { useState } from "react";
import ReactDOM from 'react-dom';
import { Box, Header, Text, Avatar, Menu, List } from "grommet";
import { MoreVertical } from "grommet-icons";
const AlarmDetailsHeader = () => {
return (
<Header className="alarmDetailsHeader" background="brand" pad="small">
<Text>"alarm1"</Text>
<Menu icon={<MoreVertical />} items={[{ label: "logout" }]} />
</Header>
);
};
const AlarmDetails = (props) => {
return (
<Box className="alarmDetails" flex={true}>
<AlarmDetailsHeader />
<Box flex={true} />
</Box>
);
};
const AlarmSummary = (item, index, state) => {
return (
<Box margin="medium">
<Text>{item.name}</Text>
</Box>
);
};
const AlarmListHeader = (props) => (
<Header className="alarmListHeader" background="brand" pad="small" border="right">
<Avatar src="//s.gravatar.com/avatar/b7fb138d53ba0f573212ccce38a7c43b?s=80" />
<Text level={5}>"Alarms</Text>
<Menu
icon={<MoreVertical />}
items={[
{ label: "First Action", onClick: () => {} },
{ label: "Second Action", onClick: () => {} }
]}
/>
</Header>
);
const AlarmList = () => {
const [alarms, setAlarms] = useState([
{
name: "alarm1"
},
{
name: "alarm2"
}
]);
return (
<Box className="alarmList" fill="vertical">
<AlarmListHeader />
{/* <List data={alarms} children={AlarmSummary} /> */}
</Box>
);
};
const App = () => {
return (
<Box className="alarmListWithDetails" direction="row" flex={true}>
<AlarmList />
<AlarmDetails />
</Box>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
.App {
font-family: sans-serif;
text-align: center;
}
.routerContainer {
display: flex;
height: "100vh";
width: "100vw";
justify-content: center;
}
.alarmListWithDetails {
max-width: "1080px";
}
.alarmList {
background-color: ivory;
width: "320px";
}
.alarmDetails {
background-color: antiquewhite;
}
.alarmListHeader {
height: '80px'
}
.alarmDetailsHeader {
height: '80px'
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/grommet/2.16.2/grommet.min.js"></script>
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<style type="text/css">
body {
margin: 0;
}
#root {
height: 100vh;
width: 100vw;
background-color: lightblue;
}
</style>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
https://codesandbox.io/s/alarm-web1-yztws?file=/src/styles.css
I am trying to achieve the below layout which is similar to the Whatsapp Web layout.
This is what I am getting at the moment:
I want to assign a max-width for the main window but that doesn't seem to take effect. I want the sidebar of the left to cover the full height of the window for which I tried using different CSS properties such as height: '100%' or fill: vertical or flex: 1 but that doesn't have any effect either.
Similarly, I want the details panel to take the complete height. I want the height of both the headers to be the same for which I specified height: 80px but that doesn't seem to have any effect either. These things work quite easily on mobile but for some reason, the web doesn't work the same.
I found flexboxfroggy.com and finished all the levels but as I mentioned, I understand the flexbox properties but the web requires some more things than just the flexbox properties to get the layout right.
Your CSS is causing some issues, but essentially you need to look at how parent and children selection works. You need to do a reset at the top level to allow 100% for child elements below it. The 100% should be working but it is set at the HTML/BODY level first. Similar with Flex, it needs to be set at a parent level before the children can display in the manner you set. Then you can use something like flex-direction: column; which will then create a whole column and then any div inside that you set to flex: 1 and you'll get a full height. You can read more here.
I wouldn't recommend using the VH or VW as they only fill the window in its current state. If that window changes then the selection will remain the previous dimension only.
An example from your CSS above is below, I've removed code that isn't working and added some.
html, body {
height: 100%;
}
body {
display: flex;
}
.App {
font-family: sans-serif;
text-align: center;
}
.routerContainer {
justify-content: center;
}
.alarmListWithDetails {
max-width: 1080px;
}
.alarmList {
background-color: ivory;
width: 320px;
}
.alarmDetails {
background-color: antiquewhite;
}
.alarmListHeader {
height: 80px;
}
.alarmDetailsHeader {
height: 80px;
}

how to get a slot content in the css content property of a pseudo ;:before element (or :;after) in a web component?

Well, I think that the question is in the title :
in a web component, with shadowRoot, I want to use a slot text-content inside the content property of a pseudo ::before or ::after element.
This could make me gain much lines.
Would you have an idea, a proposal, a solution ?
You can achieve this with the use of CSS custom properties as the source for the content of ::before and ::after and the slotchange event:
<!DOCTYPE html>
<html lang="en">
<head>
<title>WC</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
class XTest extends HTMLElement {
constructor() {
super();
// add shadow dom and insert template content
const shadowRoot = this.attachShadow({ mode: "open" });
const template = document.getElementById("x-test-template");
const templateContent = template.content;
shadowRoot.appendChild(templateContent.cloneNode(true));
}
connectedCallback() {
// get all the named slots
const slots = this.shadowRoot.querySelectorAll("slot[name]");
[...slots].forEach(slot => {
// add a listener to run when the slot changes
slot.addEventListener("slotchange", event => {
// get the slot name
const name = event.target.name;
// get the slot content
const text = event.target.assignedNodes()[0].textContent;
// update the custom property
this.style.setProperty(`--content-${name}`, `'${text}'`);
});
});
}
}
customElements.define("x-test", XTest);
</script>
</head>
<body>
<template id="x-test-template">
<style>
:host {
display: inline-block;
position: relative;
font-size: 2rem;
padding: 2rem;
}
:host::before,
:host::after {
content: "";
position: absolute;
top: 0;
font-size: 1rem;
}
:host::before {
/* set the pseudo selector content to the custom property */
content: var(--content-before, "");
left: 0;
}
:host::after {
/* set the pseudo selector content to the custom property */
content: var(--content-after, "");
right: 0;
}
slot[name] {
display: none;
}
</style>
<!-- slot for ::before -->
<slot name="before"></slot>
<!-- default slot -->
<slot></slot>
<!-- slot for ::after -->
<slot name="after"></slot>
</template>
<x-test>
<span slot="before">B</span>
<span>Hello</span>
<span slot="after">A</span>
</x-test>
</body>
</html>
#lamplightdev
Thank you for your answer.
I was looking for something wich doesn't exist yet.
So I have chose a solution with css var and a setter to set it :
class extends HTMLElement {
set content(val) {
this.setAttribute('data-content',val);
}
constructor() {
...
and, of course :
:host::before {
content: attr(data-content);
...
This seems to be the lighter solution I may imagine.
I'd like to suggest to web's standards developpers to create a new css function : slot(name) witch, with attr(...), var(...) and calc(...), could help the use of pseudo elements inside a web component.
Could someone show me the way to present this proposal ???
I do apologize for my poor english language (I'm french, nobdy's perfect).

VUE component ignoring CSS

I have the following VUE component:
<template>
<div>
<div class="bottom-footer">
{{msg}}
</div>
</div>
</template>
<script>
export default {
name: 'LayoutFooter',
data () {
return {
msg: 'my test'
}
},
mounted () {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.bottom-footer {
height: 200px;
background-color: #A7BFE8;
}
</scoped>
VUE is completely ignoring my scoped CSS. When page is rendered its simply not applied. There are no console errors. Ive tried removing the scoped attribute and its still ignored. Any ideas why VUE is doing this?
<style scoped>
.bottom-footer {
height: 200px;
background-color: #A7BFE8;
}
</style>
you need to close style

In vue.js component, how to use props in css?

I'm new to vue.js. Here is my problem:
In a *.vue file like this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: ?
}
<style>
How can I use the props color in background-color: (where is a ? now).
Thanks.
You actually can!
You should define the CSS variables in a Computed Property, then call the computed property as a style attribute to the element that will require the CSS variable, and finally you may use the variable within the tags at the bottom of your document.
new Vue({
el: '#app',
data: function() {
return {
baseFontSize: 1,
bgHoverColor: "#00cc00",
hoverContent: "Hovering!"
}
},
computed: {
cssProps() {
return {
'--hover-font-size': (this.baseFontSize * 2) + "em",
'--bg-hover-color': this.bgHoverColor,
'--hover-content': JSON.stringify(this.hoverContent)
}
}
}
})
div {
margin: 1em;
}
div.test:hover {
background-color: var(--bg-hover-color);
font-size: var(--hover-font-size);
}
div.test:hover::after {
margin-left: 1em;
content: var(--hover-content);
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app" :style="cssProps">
<div>Hover text: <input type="text" v-model="hoverContent"></div>
<div>Hover color: <input type="color" v-model="bgHoverColor"></div>
<div class="test">Hover over me</div>
</div>
Or have a look here: https://codepen.io/richardtallent/pen/yvpERW/
And here: https://github.com/vuejs/vue/issues/7346
You don't. You use a computed property and there you use the prop to return the style of the div, like this:
<template>
<div id="a" :style="style" #mouseover="mouseOver()">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color'],
computed: {
style () {
return 'background-color: ' + this.hovering ? this.color: 'red';
}
},
data () {
return {
hovering: false
}
},
methods: {
mouseOver () {
this.hovering = !this.hovering
}
}
}
</script>
<style scoped>
<style>
As we are in 2020 now, I suggest using this trick with a css function called var
<template>
<div id="a" :style="cssVars"></div>
</template>
<script>
export default {
props: ['color'],
computed: {
cssVars () {
return{
/* variables you want to pass to css */
'--color': this.color,
}
}
}
<script>
<style scoped>
#a{
background-color: var(--color);
}
</style>
This method is very useful because it allows you to update the passed values through css later on (for example when you apply hover event).
credit
I know we're talking vue 2 here, but in case anyone from vue 3 lands in this question (like I did), vue 3 introduced a much cleaner way to do this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: v-bind(color);
}
<style>
What Vue actually does behind the scenes is the same "introducing css variables through component's style process", but it sure looks much better on the eyes now.
Documentation source: https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css
Why not just use :style prop in this way:
<template>
<div :style="{ backgroundColor: color }">
</template>
<script>
export default {
props: {
color: {
type: String,
default: ''
}
}
}
</script>
Make sure you define css properties in camelCase style.
If you need css that can't be applied by a style attribute like pseudo classes or media queries, what I do is the following:
Create a globally available style component when initializing Vue (you need it as otherwise you run into linting issues). It creates a style tag that simply renders the content in the slot:
I would only use this if you really need both dynamic values in your css and css features that can't be applied to a style attribute.
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.component('v-style', {
render: function(createElement) {
return createElement('style', this.$slots.default)
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Then use it at the top of your template like this and you get the full JavaScript scope of your component and the full css syntax combined:
<template>
<v-style>
#media screen and (max-width: 820px) {
.gwi-text-media-{{ this.id }} {
background-image: url({{ mobileThumb }});
}
}
</v-style>
</template>
It seems a bit hacky to me, but it does it's job and I would rather go like this in some cases than having to add additional JS for mouse-over or resize events that have a big potential to slow down your application performance.
Vue 3 added new way of binding styles, so now you can easily bind your props to css properties.
Read source:
https://learnvue.co/2021/05/how-to-use-vue-css-variables-reactive-styles-rfc/
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
You could utilise the CSS var(--foo-bar) function. It is also useful if you are trying to pass an asset that has its own dynamic path, like Shopify does.
This method also works for styling the :before and :after elements as they refer back to the style applied on the owner element.
Using the original post example for passing a colour:
<template>
<div
id="a"
:style="{ '--colour': color }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: var(--colour);
}
</style>
Using the original post example for passing an URL:
<template>
<div
id="a"
:style="{ '--image-url': 'url(' + image + ')' }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['image']
}
</script>
<style scoped>
#a {
background-url: var(--image-url);
}
</style>
Source

Resources