href・src とは何か
href と src は、要素が「どこを指すか・何を読み込むか」を示す属性です。href はリンク先(a、link、area)、src はリソースの場所(img、script、iframe、video、audio、source)を表します。ここが重要です:href は“ナビゲーション”の対象、src は“読み込み”の対象。変更すると、リンクの遷移先や表示・実行されるリソースが即座に切り替わります。
基本の変更方法(属性かプロパティで更新する)
a要素の href を変える
<a id="help" href="/help">ヘルプ</a>
<script>
const a = document.getElementById("help");
// 属性として書き換え(相対URLをそのまま設定)
a.setAttribute("href", "/support");
// またはプロパティ(絶対URLに解決される)
a.href = "/support"; // 読み出すと "https://example.com/support" のような絶対URLになる
</script>
HTMLここが重要です:a.href は“解決後の絶対URL”、get/setAttribute(“href”) は“書かれている文字列そのもの”。検証やログ用途で意図が変わるため、使い分けます。
img の src を変える(表示を更新)
<img id="avatar" src="/img/default.png" alt="アイコン">
<script>
const img = document.getElementById("avatar");
img.src = "/img/user-42.png"; // 読み込み開始(推奨:プロパティ)
// 同等:img.setAttribute("src", "/img/user-42.png");
</script>
HTMLここが重要です:src を更新するとブラウザが即座にリソース読込を開始します。load/error イベントで完了や失敗を検知できます。
script・link の src/href を変える(動的ロード)
<script>
// スクリプトを動的追加
const s = document.createElement("script");
s.src = "/assets/app.js";
s.defer = true; // 可能なら defer
document.head.appendChild(s);
// CSS を動的追加
const l = document.createElement("link");
l.rel = "stylesheet";
l.href = "/assets/app.css";
document.head.appendChild(l);
</script>
HTMLここが重要です:既存の script/link の src/href を差し替えるより、“新しく要素を作って追加”する方が安全で副作用が少ない場面が多いです。
属性とプロパティの違い(相対・絶対、現在値の扱い)
相対URLと絶対URLの差異を理解する
<a id="about" href="/about">About</a>
<script>
const a = document.getElementById("about");
console.log(a.getAttribute("href")); // "/about"(属性文字列)
console.log(a.href); // "https://your.site/about"(絶対URLに解決)
</script>
HTMLここが重要です:ログや比較に“そのままの文字”が欲しければ属性、ネットワークや外部連携で“完全なURL”が必要ならプロパティを使います。
img の現在の表示と srcset/sizes の影響
<img id="photo" src="/img/large.jpg" srcset="/img/small.jpg 480w, /img/large.jpg 1024w" sizes="(max-width: 600px) 480px, 1024px">
<script>
const img = document.getElementById("photo");
console.log(img.currentSrc); // 実際に選ばれたソース(レスポンシブ画像のときは src でないことも)
</script>
HTMLここが重要です:レスポンシブ画像では currentSrc が“実際に表示中の画像”。src を更新する設計なら、srcset/sizes との整合性も考慮します。
安全な URL の作り方(エンコード・結合ミス防止)
クエリを安全に組み立てる
<a id="search">検索</a>
<script>
const a = document.getElementById("search");
const params = new URLSearchParams({ q: "赤い 果物&人気", page: 2 });
a.href = `/find?${params}`; // 自動で正しくエンコード
</script>
HTMLここが重要です:文字列連結で “&” や “?” を手作業するとバグの温床。URLSearchParams を使えば、確実にエンコードされ、見通しも良くなります。
危険なスキームを避ける(javascript:, data:)
ユーザー入力をそのまま href/src に入れないでください。ここが重要です:”javascript:” や不正な “data:” を避けるバリデーションを必ず行い、許可するスキーム(https、http、mailto など)をホワイトリスト化します。
読み込みの検知・失敗対策(load/error とフォールバック)
画像の読み込み成功・失敗を扱う
<img id="avatar" alt="アイコン">
<script>
const img = document.getElementById("avatar");
img.addEventListener("load", () => {
console.log("読み込み成功:", img.currentSrc);
});
img.addEventListener("error", () => {
img.src = "/img/fallback.png"; // フォールバックへ
});
img.src = "/img/user-42.png";
</script>
HTMLここが重要です:src を設定する前にイベントを登録しておくと、確実に検知できます。失敗時のフォールバックを用意すると UX が安定します。
キャッシュバスティング(最新版を確実に取得)
function bust(url) {
const u = new URL(url, location.origin);
u.searchParams.set("_", String(Date.now())); // 一意のクエリ
return u.toString();
}
// 例: img.src = bust("/img/user-42.png");
JavaScriptここが重要です:更新直後に古いキャッシュが出る問題を避けるため、デバッグや緊急対応ではクエリで一時的にバストする手が使えます(恒久対応は適切なキャッシュ設定で)。
同一オリジンとCORS(iframe・メディアの注意点)
iframe の src と同一オリジン
<iframe id="frame"></iframe>
<script>
const frame = document.getElementById("frame");
frame.src = "https://example.com/page"; // 読み込みは可能
// 異なるオリジンの iframe 内部は基本的に JS で触れない(セキュリティ仕様)
</script>
HTMLここが重要です:iframe の src 変更は簡単ですが、読み込んだ先が別オリジンなら内容にアクセスできません。意図せず依存しない設計にします。
video/audio の source 変更
<video id="v" controls></video>
<script>
const v = document.getElementById("v");
v.src = "/media/sample.mp4"; // 直接設定
v.load(); // 明示的に再読込(必要な場合)
</script>
HTMLここが重要です:形式や CORS 設定で再生に失敗することがあります。error イベントのハンドリングと代替ソースの用意を検討します。
SPA/ナビゲーション制御(href を持ちつつ遷移を抑止)
クリックでアプリ内遷移に切り替える
<a id="nav" href="/items?category=fruit">果物</a>
<script>
const nav = document.getElementById("nav");
nav.addEventListener("click", (e) => {
e.preventDefault(); // ブラウザの通常遷移を停止
const url = new URL(nav.href); // 絶対URLで安全に取得
// ここで pushState やルーターへ委譲
history.pushState({}, "", url.pathname + url.search);
// コンテンツ更新…
});
</script>
HTMLここが重要です:href は“アクセシビリティと予備の遷移”として残しつつ、クリック時は制御して SPA で処理する設計が堅牢です。
具体例(動的リンク生成・画像プレビュー・ダウンロード)
検索リンクを安全に生成
<a id="search">検索</a>
<script>
const link = document.getElementById("search");
function setSearchLink(q, page = 1) {
const params = new URLSearchParams({ q, page });
link.href = `/find?${params}`;
link.textContent = `「${q}」を検索`;
}
setSearchLink('赤い 果物&人気', 2);
</script>
HTMLここが重要です:URLSearchParams で文字列化し、リンク表示文言は textContent で安全に更新します。
ファイル選択の画像プレビュー
<input id="file" type="file" accept="image/*">
<img id="preview" alt="プレビュー">
<script>
const file = document.getElementById("file");
const preview = document.getElementById("preview");
file.addEventListener("change", () => {
const f = file.files?.[0];
if (!f) return;
const url = URL.createObjectURL(f); // 一時URLを作る
preview.src = url;
preview.onload = () => URL.revokeObjectURL(url); // 読み込み後に解放
});
</script>
HTMLここが重要です:ローカルファイルのプレビューには Object URL を使い、読み込み後に revoke してリソースを解放します。
ダウンロードリンクの切り替え
<a id="dl" download>ダウンロード</a>
<script>
const dl = document.getElementById("dl");
function setDownload(name, blob) {
const url = URL.createObjectURL(blob);
dl.href = url;
dl.download = name; // 保存ファイル名
}
</script>
HTMLここが重要です:download 属性で保存名を指定。Object URL は使い終わったら revoke してメモリを管理します。
よくある落とし穴と対策(タイミング・相対/絶対・検証)
描画・読み込みタイミングを意識する
画像や外部リソースの更新は、イベントを使って“完了”を待つのが安全です。ここが重要です:load/error をハンドリングし、UIの状態(ローディング表示など)と同期させます。
相対パスの基準は“現在のドキュメント URL”
相対 href/src は、<base> タグや現在ページの URL に依存して解決されます。ここが重要です:意図しない基準にならないよう、可能なら絶対URLや new URL(relative, origin) で明示します。
入力値の検証とホワイトリスト
ユーザー入力を URL に混ぜる前に、許可するパターンのホワイトリストを適用します。ここが重要です:スキーム・ホスト・パスの検証で、javascript: や不正な data: を拒否し、XSSやオープンリダイレクトを防ぎます。
まとめ
href は“遷移先”、src は“読み込むリソース”。変更は属性(get/setAttribute)とプロパティ(a.href/img.src)の使い分けが鍵で、相対/絶対や currentSrc の違いを理解する。URL は URLSearchParams/new URL で安全に組み立て、危険なスキームを拒否。読み込みは load/error を監視し、フォールバックやキャッシュ対策を用意。iframe・メディアは CORS と仕様を踏まえ、SPAでは href を残しつつ制御する。これらを守れば、初心者でも安全で意図通りのリンク・リソース切り替えが書けます。
