my code
public folder:
public
└ images
└ paper-light.png
next.config.js:
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
};
if (process.env.NODE_ENV === 'production') {
nextConfig.basePath = '/blog';
nextConfig.assetPrefix = '/blog';
}
module.exports = nextConfig;
global.css:
body {
background-image: url('/images/paper-light.png');
}
out code
expected global.css:
body {
background-image: url('/blog/images/paper-light.png');
}
actual result global.css
body {
background-image: url('/images/paper-light.png');
}
How can I fix it to expected?
Related
I wrote tailwind.config.js as belows to use new css length types such as "lvh", "svh".
module.exports = {
theme: {
extend: {
height: {
"screen": "100dvh",
"screen-small": "100svh",
"screen-large": "100lvh"
}
}
}
}
then it successfully exports
.h-screen {
height: 100dvh;
}
But I want to get with fallback properties like
.h-screen {
height: 100vh; /* fallback for Opera, IE and etc. */
height: 100dvh;
}
Is there any nice way to export fallback properties with Tailwind CSS?
I had no idea to try
Pass an array as property
module.exports = {
theme: {
extend: {
height: {
screen: ['100vh /* fallback for Opera, IE and etc. */', '100dvh'],
}
}
}
}
This will generate
.h-screen {
height: 100vh /* fallback for Opera, IE and etc. */;
height: 100dvh;
}
DEMO
Note: I'm not 100% sure it is supposed way to do it as editor shows error because we are passing not string but array of strings.
Another way is to create utility with layer
#layer utilities {
.h-my-screen {
height: 100vh; /* fallback for Opera, IE and etc. */
height: 100dvh;
}
}
In case if you wish to use reserved h-screen name approach is similar but it will stack default (100vh) and new value (100dvh) in correct order you need - but it is just coincidence
#layer utilities {
.h-screen {
height: 100dvh;
}
}
Same thing using Tailwind plugin
const plugin = require('tailwindcss/plugin')
/** #type {import('tailwindcss').Config} */
module.exports = {
// ...
plugins: [
plugin(function ({ addBase, addComponents, addUtilities, theme }) {
addUtilities({
'.h-screen': {
height: '100dvh',
}
})
})
],
}
Created both way utility h-screen will now generate
.h-screen {
height: 100vh;
height: 100dvh;
}
Note: when using JS syntax object CANNOT contain similar keys (height in your case) but it may accept an array of values in defined order
// Wrong
addUtilities({
'.h-my-screen': {
height: '100vh /* fallback for Opera, IE and etc. */',
height: '100dvh',
}
})
// Correct
addUtilities({
'.h-my-screen': {
height: ['100vh /* fallback for Opera, IE and etc. */', '100dvh'],
}
})
I tried to change label's margin (see the attached image to the question) from px to em/rem, but i don't know where i should write styles to structure. I can't find in MUI documentation "adjacent sibling combinator".
createTheme({
MuiTextField: {
defaultProps: {
// props
},
styleOverrides: {
root: {
// styles
}
}
}
})
generated css style in inspector tab
If you are using material-ui 5:
import { createTheme } from '#mui/material';
const theme = createTheme({
components: {
MuiTextField: {
styleOverrides: {
root: {
'& label': {
margin: '2rem',
},
},
},
},
},
});
export default theme;
https://mui.com/pt/material-ui/customization/theme-components/
I finally resolve it ;) I added to InputLabel this line "& + .MuiInputBase-root" to change TextField's (and another inputs) label
MuiInputLabel: {
defaultProps: {
// props
},
styleOverrides: {
root: {
// styles
"& +.MuiInputBase-root": {
marginTop: '2em'
}
}
}
}
I'm using next-mdx-remote to make use of MDX in my Next.js project.
I've been following JetBrains WebStorm guide to build this, here they've used bootstrap as their CSS but my choice of CSS framework was tailwind css.
The thing is when I install tailwind css or any other CSS based on tailwind css like flowbite, the MDX page loses it's styling.
Expected
What I Get after adding tailwind
tailwind.config.js
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Head from "next/head";
import Script from "next/script";
import Nav from "../components/Nav";
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Head>
{/* <link
rel="stylesheet"
href="https://unpkg.com/#themesberg/flowbite#1.2.0/dist/flowbite.min.css"
/> */}
</Head>
<Script src="https://unpkg.com/#themesberg/flowbite#1.2.0/dist/flowbite.bundle.js" />
<Nav />
<Component {...pageProps} />
</>
);
}
export default MyApp;
globals.css
#tailwind base;
#tailwind components;
#tailwind utilities;
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
[blogId].tsx
// import fs from "fs";
import matter from "gray-matter";
import path from "path";
import { serialize } from "next-mdx-remote/serialize";
import { MDXRemote } from "next-mdx-remote";
import { connectToDatabase } from "../../utils/mongodb";
import { ObjectId } from "mongodb";
const BlogPg = ({ frontMatter: { title }, MDXdata }) => {
return (
<div className="px-5 md:px-80 py-10">
<p className="text-5xl mb-4">{title}</p>
<MDXRemote {...MDXdata} />
</div>
);
};
export const getStaticPaths = async () => {
let { db } = await connectToDatabase();
const posts = await db.collection("blogs").find({}).toArray();
const paths = posts.map((post) => ({
params: {
blogId: post._id.toString(),
},
}));
return {
paths,
fallback: false,
};
};
export const getStaticProps = async ({ params: { blogId } }) => {
// const fileContent = fs.readFileSync(
// path.join("posts", blogId) + ".mdx",
// "utf-8"
// );
let { db } = await connectToDatabase();
const post = await db
.collection("blogs")
.find({ _id: new ObjectId(blogId) })
.toArray();
const { data: frontMatter, content } = matter(post[0].text);
const MDXdata = await serialize(content);
return {
props: {
frontMatter,
blogId,
MDXdata,
},
};
};
export default BlogPg;
You may change content to purge and add require('#tailwindcss/typography') to plugins in tailwind.config.js.
And then to see typography changes you should cover your <MDXRemote .../> with a prose named div.
tailwind.config.js
module.exports = {
purge: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [require('#tailwindcss/typography')],
};
[blogId].tsx
...
<div className="prose">
<MDXRemote {...MDXdata} />
</div>
</div>
);
};
...
I'm trying to place this behind my login box. The svg element is rendering but none of the contents. The rest of the login screen as well as the rest of the website works as expected. Even when I comment out all of the other html and JSX code, the svg doesn't render the particles within it. I even have another D3 element (just a graph) rendering just fine, so I suspect that there's an issue with D3-force. I have the latest d3 and d3-force installed from npm.
Here's all the relevant CSS:
* {
margin: 0;
padding: 0;
}
html {
font-size: 62.5%;
}
body {
font-family: Helvetica, Arial, sans-serif;
font-size: $base-font-size;
//background-color: $grey;
}
.boxed-view {
align-items: center;
background: $boxed-view-overlay-bg;
display: flex;
justify-content: center;
height: 100vh;
width: 100vw;
}
.boxed-view__box {
background-color: $boxed-view-bg;
margin-bottom: $space;
padding: 2.4rem;
text-align: center;
width: 28rem;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
overflow: scroll;
}
And here's all the relevant JS:
import d3 from 'd3';
import React from 'react';
import d3_force from 'd3-force';
import {Session} from 'meteor/session';
import {Tracker} from 'meteor/tracker';
import {Bodies} from '../api/bodies';
export default class BrownianSplash extends React.Component {
constructor(props) {
super(props);
this.state = {
bodies: [],
isOpen_add: false,
isOpen_view: false,
error: ''
};
}
onSubmit(e) {
let username = this.refs.username.value.trim();
let password = this.refs.password.value.trim();
e.preventDefault(); // prevent page refresh
Meteor.loginWithPassword({username}, password, (err) => {
if (err) {
console.log('Login callback', err);
this.setState({error: err.reason});
} else {
this.setState({error: ''});
}
});
}
componentDidMount() {
this.bodyNamesTracker = Tracker.autorun(() => {
Meteor.subscribe('bodies_names');
const bodies = Bodies.find({}).fetch();
this.setState({bodies});
});
}
componentWillUnmount() {
this.bodyNamesTracker.stop(); // we don't want to set the state every time the page is loaded
}
renderAnimation() {
const INIT_DENSITY = 0.00025, // particles per sq px
PARTICLE_RADIUS_RANGE = [1, 12],
PARTICLE_VELOCITY_RANGE = [0, 4];
const canvasWidth = window.innerWidth,
canvasHeight = window.innerHeight,
svgCanvas = d3.select('svg#canvas')
.attr('width', canvasWidth)
.attr('height', canvasHeight);
const forceSim = d3_force.forceSimulation()
.alphaDecay(0)
.velocityDecay(0)
.on('tick', particleDigest)
.force('bounce', d3_force.forceBounce()
.radius(d => d.r)
)
.force('container', d3_force.forceSurface()
.surfaces([
{from: {x:0,y:0}, to: {x:0,y:canvasHeight}},
{from: {x:0,y:canvasHeight}, to: {x:canvasWidth,y:canvasHeight}},
{from: {x:canvasWidth,y:canvasHeight}, to: {x:canvasWidth,y:0}},
{from: {x:canvasWidth,y:0}, to: {x:0,y:0}}
])
.oneWay(true)
.radius(d => d.r)
);
// Init particles
onDensityChange(INIT_DENSITY);
// Event handlers
function onDensityChange(density) {
const newNodes = genNodes(density);
// d3.select('#numparticles-val').text(newNodes.length);
// d3.select('#density-control').attr('defaultValue', density);
forceSim.nodes(newNodes);
}
function onElasticityChange(elasticity) {
// d3.select('#elasticity-val').text(elasticity);
// forceSim.force('bounce').elasticity(elasticity);
// forceSim.force('container').elasticity(elasticity);
}
//
function genNodes(density) {
const numParticles = Math.round(canvasWidth * canvasHeight * density),
existingParticles = forceSim.nodes();
// Trim
if (numParticles < existingParticles.length) {
return existingParticles.slice(0, numParticles);
}
// Append
return [...existingParticles, ...d3_force.range(numParticles - existingParticles.length).map(() => {
const angle = Math.random() * 2 * Math.PI,
velocity = Math.random() * (PARTICLE_VELOCITY_RANGE[1] - PARTICLE_VELOCITY_RANGE[0]) + PARTICLE_VELOCITY_RANGE[0];
return {
x: Math.random() * canvasWidth,
y: Math.random() * canvasHeight,
vx: Math.cos(angle) * velocity,
vy: Math.sin(angle) * velocity,
r: Math.round(Math.random() * (PARTICLE_RADIUS_RANGE[1] - PARTICLE_RADIUS_RANGE[0]) + PARTICLE_RADIUS_RANGE[0])
}
})];
}
function particleDigest() {
let particle = svgCanvas.selectAll('circle.particle').data(forceSim.nodes().map(hardLimit));
particle.exit().remove();
particle.merge(
particle.enter().append('circle')
.classed('particle', true)
.attr('r', d=>d.r)
.attr('fill', 'darkslategrey')
)
.attr('cx', d => d.x)
.attr('cy', d => d.y);
}
function hardLimit(node) {
// Keep in canvas
node.x = Math.max(node.r, Math.min(canvasWidth-node.r, node.x));
node.y = Math.max(node.r, Math.min(canvasHeight-node.r, node.y));
return node;
}
}
render() {
return (
<div>
<svg id="canvas"></svg>
<div id="controls"></div>
<div className='boxed-view'>
{/* D3 background goes here */}
{/* <svg className='boxed-view'></svg> */}
<div className='boxed-view__box'>
<h1>Login</h1>
{this.state.error ? <p>{this.state.error}</p> : undefined}
<form onSubmit={this.onSubmit.bind(this)} className='boxed-view__form'>
<input type="text" name='username' placeholder="Josiah Carberry" ref='username'/>
<input type="password" name='password' ref='password'/>
<button className='button'>Let's Go</button>
</form>
</div>
</div>
</div>
);
}
}
So I didn't know that d3-force-bounce and d3-force-surface existed. They're both npm packages and are default exports. The methods d3.forceBounce() and d3.forceSurface() are methods of d3ForceBounce and d3ForceSurface, not d3. Finally, I forgot to call renderAnimation() in the JSX.
I'm using this code from here: http://buildwithreact.com/article/fade-in-image-recipe
currently have it as my component:
<ImageComponent src="https://docs.google.com/uc?id=0B0huBtqYaof7NFV6Nnpkalk5cEU" />
Now when I go to google chrome and inspect the element, it has the class names of image and image-loaded but when take a look at the css, there is no css even though I added it to my style sheet. Does anyone know how to fix this?
.image { opacity: 0; transition: opacity 500ms ease-in; }
.imageloaded { opacity: 1; }
Here is the css I imported(code above)
import React, { Component } from 'react';
import ImageComponent from './image.component.jsx';
import styles from './css/Header.css';
export default class Home extends Component {
constructor() {
super();
this.state = {
lightboxIsOpen: false,
currentImage: 0,
}
this.closeLightbox = this.closeLightbox.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
}
return(
<div>
<Grid>
<div>
<ImageComponent src="https://docs.google.com/uc?id=0B0huBtqYaof7NFV6Nnpkalk5cEU" />
</div>
</Grid>
</div>
)
}
Here is the component for ImageComponent
import classNames from 'classnames';
import React, { Component } from 'react';
import ReactDOM, { render } from 'react-dom';
const ImageComponent = React.createClass({
getInitialState: function() {
return {
loaded: false
};
},
onImageLoad: function() {
if (this.isMounted()) {
this.setState({ loaded: true });
}
},
componentDidMount: function() {
var imgTag = ReactDOM.findDOMNode(this.refs.img);
var imgSrc = imgTag.getAttribute('src');
var img = new window.Image();
img.onload = this.onImageLoad;
img.src = imgSrc;
},
render: function() {
var { className, ...props } = this.props;
var imgClasses = 'image';
var rootClassName = classNames(className, 'image', {
'imageloaded': this.state.loaded,
});
return (
<img ref="img" {...props} className={rootClassName} />
);
}
});
export default ImageComponent;
Try passing image url as props to imagecomponent and directly attach it to img element.