Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

node.jsとTypeScriptでDOM操作しながら、同じページで2つのCSSを使いたい

初質問なので、質問の仕方に至らないところがあるかもしれません
ご不明点がございましたらご指摘いただけると幸いです。

解決したいこと

大学の課外活動の紹介サイトを作成しているのですが、
同じhtml内で2つのCSSファイルを利用しようと思いつき

  • BootStrapのCSSファイル
    (ローカルに落としてきたもの、学内プロキシ下だとURLから使おうとすると動かない
    ことが多いため、ローカルで利用している)
  • あとから用意したCSSファイル
    を利用しようとしたところ、どちらも動かないという事態が発生しました。

HTML単体を普通にブラウザで動かすと動作するのですが、TypeScriptを使ってDOMを操作しているので、その状態だとDOM操作ができないです。ちなみにnode.jsとTypeScriptのバージョンは以下の通りです。(OSはWindows11です)

  • node.jsのバージョン「v16.14.0」
  • TypeScriptのバージョン「Version 4.6.2」
  • 実行する際のコマンド「npm run serve」

どうにかしてnode.jsとTypeScriptを使いながら2つのCSSを活かして実行したいです。
ご回答よろしくお願いします。

現状

image.png

###ディレクトリ構成
image.png

ソースコード

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <title>responsive jsSITE</title>
        <!-- <link href="css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
        <link href="css/add-style.css" rel="stylesheet"> -->
        <!-- <style type="text/css">
            @import url(css/add-style.css);
            @import url(css/bootstrap.min.css);
        </style> -->
        <link href="css/fusion.css" rel="stylesheet">
        <script src="main.js"></script>
    </head>
    <body>
        <h1 class="bg-warning text-white p-2">RoboCup@HOME</h1>
        <div class="ZoomOutText">
            <a href="#">
                <span class="mask">
                    <img src="mimichan2.png" alt="みみちゃん">
                    <span class="cap">一緒にかわいいロボットつくりませんか?</span>
                </span>
            </a>
        </div>
        <p id="tap_para">下のボタンをクリックしてみよう!!</p>
        <button type="button" class="btn btn-primary" id="tap">PUSH!!</button>
    </body>
</html>

コメントアウトしている部分は、実際に動かそうとして動かなかった
コードを残してあります(あとから調べたものが、以前やってできなかったモノと同じでないかどうか確認するため)

あとから用意したCSSファイル(ファイル名:add-style.css)

.ZoomOutText{
    position: relative; /*テキストの基点位置の定義*/
}

.ZoomOutText span.mask{
    position: relative; /*背景色の基点位置を定義*/
    transition: .3s ease-in-out; /*移り変わる速さの指定*/
    display: block;/*画像を括るspanタグをブロック要素とする*/
    line-height: 0;/*行の高さ0*/
    overflow: hidden;/*高さからはみ出たものは隠す*/
}

.ZoomOutText:hover span.mask::before{
    /*hoverした時の変化*/
    content: "";
    position: absolute;
    z-index: 2;
    top: 10px;
    left: 10px;
    width: calc(100% - 20px);
    height: calc(100% - 20px);
    background: rgba(red, green, blue, 5);/*背景色*/

}

.ZoomOutText img{
    transform: scale(1.2);
    filter: blur(0);
    transition: .3s ease-in-out;/*移り変わる速さ*/
}

.ZoomOutText:hover img{
    /*hoverした時の変化*/
    transform: scale(1);/*縮小の値を変更*/
    filter: blur(2px);/*ぼかし具合*/
}

.ZoomOutText span.cap{
    opacity: 0;
    transition: .5s ease-in-out;/*移り変わる速さを変更*/
    position: absolute;
    z-index: 3;/*テキストを前面に出す*/
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    color: #fff;/*テキストの色*/
    line-height: 1.5;/*行の高さ*/
}

.ZoomOutText:hover span.cap{
    /*hover時の変化*/
    opacity: 1;
}

このプログラムは https://coco-factory.jp/ugokuweb/move02/7-21/ に記載されているものを(コメントは少し変えましたが)そのまま使っています。

@importを使おうとしたもの(ファイル名:fusion.css)

@charset "UTF-8";
@import url(add-style.css);
@import url(bootstrap.min.css);

[追記]
package.json

{
  "name": "my-webpack-project",
  "version": "1.0.0",
  "description": "My webpack project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode=production --node-env=production",
    "build:dev": "webpack --mode=development",
    "build:prod": "webpack --mode=production --node-env=production",
    "watch": "webpack --watch",
    "serve": "webpack serve"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Tiamat-KIT/framework_testy.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/Tiamat-KIT/framework_testy/issues"
  },
  "homepage": "https://github.com/Tiamat-KIT/framework_testy#readme",
  "devDependencies": {
    "@types/node": "^17.0.23",
    "autoprefixer": "^10.4.4",
    "css-loader": "^6.7.1",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.6.0",
    "postcss": "^8.4.12",
    "postcss-loader": "^6.2.1",
    "prettier": "^2.5.1",
    "style-loader": "^3.3.1",
    "ts-loader": "^9.2.8",
    "typescript": "^4.6.3",
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4",
    "workbox-webpack-plugin": "^6.5.1"
  },
  "dependencies": {
    "@webpack-cli/generators": "^2.4.2",
    "tailwindcss": "^3.0.23"
  }
}

index.ts

import { time } from "console"

let tap:HTMLButtonElement
let tap_para:HTMLParagraphElement
let button = document.getElementById('tap')
button.addEventListener('click',()=>{
    tap = document.querySelector("#tap")
    tap_para = document.querySelector("#tap_para")
    tap.textContent = 'Good!'
    tap_para.textContent = 'change!'
    setTimeout('tap.textContent = "PUSH!!"',1000)
    setTimeout('tap_para.textContent = "下のボタンをクリックしてみよう!!"',1000)
})

自分で試したこと

1.link hrefでそれぞれファイルを読み込ませる

2.HTML内に@importを記述する。
3.CSSファイルに@importを記述して、2つのCSSを1つのCSSファイルに読み込ませてからHTMLに読み込ませて動かしている

2,3の方法の参考サイト:https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1110872181

0

3Answer

試しにserveで環境を作ってみたところ、此方では問題なくcssが適用されるようでした。

HTML単体を普通にブラウザで動かすと動作するのですが、TypeScriptを使ってDOMを操作しているので、その状態だとDOM操作ができないです。

npm run serveで実行しているということは、何かしらのパッケージを使ってサーバが動いていると思いますが…
いずれにせよそのTypeScriptで何を動かしているのかの情報が必要です。
package.jsonも併せて貼ったほうが良いかもしれません。

1Like

Comments

  1. ご指摘ありがとうございます。
    package.jsonと、tsファイルの中身、それに加えてディレクトリ構成も追記してみます。

おそらくwebpack周りの設定が怪しいというところからの推測になりますが(webpack.config.jsの内容もあると正確な回答ができるかも),html-webpack-pluginでhtmlをバンドルしたまま別ディレクトリに出力していたりしてませんか?

具体的にはこんなことをしていたりすると↓:

webpack.config.js
module.exports = {
    //...
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'main.js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'My App',
            filename: 'index.html',
            template: './index.html'
        })
    ],
    devServer: {
        static: {
            directory: path.join(__dirname, 'dist')
        }
    }
}

index.htmlとmain.jsだけがdistディレクトリに出力されて,htmlからはcssやmimichan2.pngが見えなくなります.

参照するディレクトリを全部__dirnameにしてしまえば動きはするのですが,折角webpackやstyle-loaderを使用しているのですからimportでcssを使うほうがwebpack的にはベターかなと思います.

src/index.ts
//相対パスは適宜調整してください
import "../css/add-style.css"

ちなみにbootstrapに関してはnpmパッケージをwebpackで使うこともできますので参考にしてみてください。

本題とは関係ないですが,DOMを弄る際は必ずwindow.onloadが済んでからじゃないとダメです.

src/index.ts
window.onload = () => {
    let tap_para = document.getElementById('tap_para')
    let button = document.getElementById('tap')
    button.addEventListener('click', () => {
        button.textContent = 'Good!'
        tap_para.textContent = 'change!'
        setTimeout(() => {
            button.textContent = "PUSH!!"
            tap_para.textContent = "下のボタンをクリックしてみよう!!"
        }, 1000)
    })
}
1Like

Comments

  1. この回答の下部に念のため、webpack.config.jsの構成を書いておきました。
    ひとまず、ご回答いただいた部分を修正してみます。ありがとうございます。

webpack.config.js

// Generated using webpack-cli https://github.com/webpack/webpack-cli

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");

const isProduction = process.env.NODE_ENV == "production";

const stylesHandler = isProduction
  ? MiniCssExtractPlugin.loader
  : "style-loader";

const config = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "dist"),
  },
  devServer: {
    open: true,
    host: "localhost",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "index.html",
    }),

    // Add your plugins here
    // Learn more about plugins from https://webpack.js.org/configuration/plugins/
  ],
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/i,
        loader: "ts-loader",
        exclude: ["/node_modules/"],
      },
      {
        test: /\.css$/i,
        use: [stylesHandler, "css-loader", "postcss-loader"],
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
        type: "asset",
      },

      // Add your rules for custom modules here
      // Learn more about loaders from https://webpack.js.org/loaders/
    ],
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
};

module.exports = () => {
  if (isProduction) {
    config.mode = "production";

    config.plugins.push(new MiniCssExtractPlugin());

    config.plugins.push(new WorkboxWebpackPlugin.GenerateSW());
  } else {
    config.mode = "development";
  }
  return config;
};

念のため、webpack.config.jsの内容も記載しておきます。
僕自身がDOMやTypeScriptなどの技術の扱いが未熟なので、window.onloadの存在すら知りませんでした。参照ディレクトリ周りの設定、CSSのインポート、パッケージの利用を色々工夫してみようと思います。ありがとうございます。
webpack.config.js - framework_testy - Visual Studio Code 2022_04_05 21_55_54.png

0Like

Your answer might help someone💌